「iOS」——KVC

源碼學習

  • iOS底層學習:KVC 底層原理
    • 一、核心 API 與功能特性
      • **常用方法**
    • KVC 設值 底層原理
    • KVC 取值 底層原理
    • 自定義KVC
      • 設值
      • 取值
      • **特性:無隱私訪問**
        • **原理**
    • 四、多元應用場景
      • 1. **動態數據處理**
        • (1)字典轉模型
        • (2)模型轉字典
      • 2. **系統控件定制**
      • 3. **高階集合操作**
      • **(1) 聚合運算**
      • **(2) 數組映射**
      • **(3) 嵌套集合操作**


iOS底層學習:KVC 底層原理

在 iOS 開發中,KVC(Key-Value Coding,鍵值編碼) 是一種通過字符串鍵名間接訪問對象屬性的機制,基于NSKeyValueCoding協議實現。它提供了動態訪問對象屬性的能力,無需直接調用存取方法或操作實例變量,極大提升了代碼的靈活性和動態性。

一、核心 API 與功能特性

KVC 提供了一套完整的 API 用于屬性的讀寫、驗證和集合操作,核心方法如下:

常用方法

  • 通過key 設值/取值
    • 方法原型
//直接通過Key來取值
- (nullable id)valueForKey:(NSString *)key;//通過Key來設值
- (void)setValue:(nullable id)value forKey:(NSString *)key;

? 使用:

// 通過鍵名獲取屬性值
id value = [object valueForKey:@"propertyKey"]; 
// 通過鍵路徑獲取嵌套屬性值(如:person.student.name)
id value = [object valueForKeyPath:@"keyPath"]; 
  • 通過keyPath (即路由)設值/取值

    • 方法原型
    //通過KeyPath來取值
    - (nullable id)valueForKeyPath:(NSString *)keyPath; //通過KeyPath來設值                 
    - (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;  
    

    使用

    // 通過鍵名設置屬性值
    [object setValue:newValue forKey:@"propertyKey"]; 
    // 通過鍵路徑設置嵌套屬性值
    [object setValue:newValue forKeyPath:@"keyPath"]; 
    

其他方法

//默認返回YES,表示如果沒有找到Set<Key>方法的話,會按照_key,_iskey,key,iskey的順序搜索成員,設置成NO就不這樣搜索
+ (BOOL)accessInstanceVariablesDirectly;//KVC提供屬性值正確性驗證的API,它可以用來檢查set的值是否正確、為不正確的值做一個替換值或者拒絕設置新值并返回錯誤原因。
- (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;//這是集合操作的API,里面還有一系列這樣的API,如果屬性是一個NSMutableArray,那么可以用這個方法來返回。
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;//如果Key不存在,且KVC無法搜索到任何和Key有關的字段或者屬性,則會調用這個方法,默認是拋出異常。
- (nullable id)valueForUndefinedKey:(NSString *)key;//和上一個方法一樣,但這個方法是設值。
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;//如果你在SetValue方法時面給Value傳nil,則會調用這個方法
- (void)setNilValueForKey:(NSString *)key;//輸入一組key,返回該組key對應的Value,再轉成字典返回,用于將Model轉到字典。
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;

通過 validateValue:forKey:error: 方法驗證屬性值的合法性:

- (BOOL)validateValue:(inout id _Nullable __autoreleasing *)ioValue forKey:(NSString *)inKey error:(out NSError **)outError {// 自定義驗證邏輯(如:限制數值范圍、字符串長度等)if ([inKey isEqualToString:@"age"] && [(NSNumber *)*ioValue integerValue] < 0) {*ioValue = @(0); // 修正非法值if (outError) {*outError = [NSError errorWithDomain:@"ValidationError" code:0 userInfo:@{NSLocalizedDescriptionKey:@"Age cannot be negative"}];}return NO;}return YES;
}

KVC 設值 底層原理

在日常開發中,針對對象屬性的賦值,一般有以下兩種方式

  • 直接通過setter方法賦值
  • 通過KVC鍵值編碼的相關API賦值
LGPerson *person = [[LGPerson alloc] init];
// 1、一般setter 方法
person.name      = @"CJL_哈哈";
// 2、KVC方式
[person setValue:@"CJL_嘻嘻" forKey:@"name"]; 

下面針對使用最多的KVC設值方法:setValue:forKey,來進行其底層原理的探索。

首先進入setValue:forKey的聲明,發現是在Foundation框架中,而Foundation框架是不開源的,所以我們通過觀看官方文檔研究。

當調用setValue:forKey:設置屬性value時,其底層的執行流程為

  • 【第一步】首先查找是否有這三種setter方法,按照查找順序為set<Key>:-> _set<Key> -> setIs<Key>

    • 如果有其中任意一個setter方法,則直接設置屬性的value(注意:key是指成員變量名,首字符大小寫需要符合KVC的命名規范)
    • 如果都沒有,則進入【第二步】
  • 【第二步】:如果沒有第一步中的三個簡單的setter方法,則查找accessInstanceVariablesDirectly是否返回YES

    • 如果返回YES

      ,則查找間接訪問的實例變量進行賦值,查找順序為:_<key> -> _is<Key> -> <key> -> is<Key>

      • 如果找到其中任意一個實例變量,則賦值
      • 如果都沒有,則進入【第三步】
    • 如果返回NO,則進入【第三步】

  • 【第三步】如果setter方法 或者 實例變量都沒有找到,系統會執行該對象的setValue:forUndefinedKey:方法,默認拋出NSUndefinedKeyException類型的異常

綜上所述,KVC通過 setValue:forKey: 方法設值的流程以設置LGPerson的對象person的屬性name為例,如下圖所示

請添加圖片描述

KVC 取值 底層原理

同樣的,我們可以通過官方文檔分析KVC取值的底層原理

當調用valueForKey:時,其底層的執行流程如下

  • 【第一步】首先查找getter方法,按照

    get<Key> -> <key> -> is<Key> -> _<key>
    

    的方法順序查找,

    • 如果找到,則進入【第五步】
    • 如果沒有找到,則進入【第二步】
  • 【第二步】如果第一步中的getter方法沒有找到,KVC會查找. countOf <Key>和objectIn <Key> AtIndex :和<key> AtIndexes

    • 如果找到countOf <Key>和其他兩個中的一個,則會創建一個響應所有NSArray方法的集合代理對象,并返回該對象,即NSKeyValueArray,是NSArray子類。代理對象隨后將接收到的所有NSArray消息轉換為countOf<Key>,objectIn<Key> AtIndex:和<key>AtIndexes:消息的某種組合,用來創建鍵值編碼對象。如果原始對象還實現了一個名為get<Key>:range:之類的可選方法,則代理對象也將在適當時使用該方法(注意:方法名的命名規則要符合KVC的標準命名方法,包括方法簽名。)
    • 如果沒有找到這三個訪問數組的,請繼續進入【第三步】
  • 【第三步】如果沒有找到上面的幾種方法,則會同時查找countOf <Key>,enumeratorOf<Key>和memberOf<Key>這三個方法

    • 如果這三個方法都找到,則會創建一個響應所有NSSet方法的集合代理對象,并返回該對象,此代理對象隨后將其收到的所有NSSet消息轉換為countOf<Key>,enumeratorOf<Key>和memberOf<Key>:消息的某種組合,用于創建它的對象
    • 如果還是沒有找到,則進入【第四步】
  • 【第四步】如果還沒有找到,檢查類方法InstanceVariablesDirectly是否YES,依次搜索 _<key>,_is<Key>,<key>或is<Key>的實例變量

    • 如果搜到,直接獲取實例變量的值,進入【第五步】
  • 【第五步】根據搜索到的屬性值的類型,返回不同的結果

    • 如果是對象指針,則直接返回結果
    • 如果是NSNumber支持的標量類型,則將其存儲在NSNumber實例中并返回它
    • 如果是是NSNumber不支持的標量類型,請轉換為NSValue對象并返回該對象
  • 【第六步】如果上面5步的方法均失敗,系統會執行該對象的valueForUndefinedKey:方法,默認拋出NSUndefinedKeyException類型的異常

綜上所述,KVC通過 valueForKey: 方法取值的流程以設置LGPerson的對象person的屬性name為例,如下圖所示

請添加圖片描述

自定義KVC

根據上述KVC設值和取值的邏輯,我們可以寫一個自定義的KVC。

設值

自定義KVC設置流程,主要分為以下幾個步驟:

  • 1、判斷key非空
  • 2、查找setter方法,順序是:setXXX、_setXXX、 setIsXXX
  • 3、判斷是否響應accessInstanceVariablesDirectly方法,即間接訪問實例變量,
    • 返回YES,繼續下一步設值,
    • 如果是NO,則崩潰
  • 4、間接訪問變量賦值(只會走一次),順序是:_key、_isKey、key、isKey
    • 4.1 定義一個收集實例變量的可變數組
    • 4.2 通過class_getInstanceVariable方法,獲取相應的 ivar
    • 4.3 通過object_setIvar方法,對相應的 ivar 設置值
  • 5、如果找不到相關實例變量,則拋出異常
@interface NSObject (GCKVC)//設值
- (void)gc_setValue:(nullable id)value forKey:(NSString *)key;
//取值
- (nullable id)gc_valueForKey:(NSString *)key;@end@implementation NSObject (GCKVC)//設值
- (void)gc_setValue:(nullable id)value forKey:(NSString *)key{// 1、判斷key 是否存在if (key == nil || key.length == 0) return;// 2、找setter方法,順序是:setXXX、_setXXX、 setIsXXX// key 要大寫NSString *Key = key.capitalizedString;// key 要大寫NSString *setKey = [NSString stringWithFormat:@"set%@:", Key];NSString *_setKey = [NSString stringWithFormat:@"_set%@:", Key];NSString *setIsKey = [NSString stringWithFormat:@"setIs%@:", Key];if ([self gc_performSelectorWithMethodName:setKey value:value]) {NSLog(@"*************%@*************", setKey);return;}else if([self gc_performSelectorWithMethodName:_setKey value:value]){NSLog(@"*************%@*************", _setKey);return;}else if([self gc_performSelectorWithMethodName:setIsKey value:value]){NSLog(@"*************%@*************", setIsKey);return;}// 3、判斷是否響應`accessInstanceVariablesDirectly`方法,即間接訪問實例變量,返回YES,繼續下一步設值,如果是NO,則崩潰if (![self.class accessInstanceVariablesDirectly]) {@throw [NSException exceptionWithName:@"GCUnKnownKeyException" reason:[NSString stringWithFormat:@"****[%@ valueForUndefinedKey:]: this class is not key value coding-compliant for the key name.****",self] userInfo:nil];}// 4、間接訪問變量賦值,順序為:_key、_isKey、key、isKey// 4.1 定義一個收集實例變量的可變數組NSMutableArray *mArray = [self getIvarListName];// _<key> _is<Key> <key> is<Key>NSString *_key = [NSString stringWithFormat:@"_%@", key];NSString *_isKey = [NSString stringWithFormat:@"_is%@", Key];NSString *isKey = [NSString stringWithFormat:@"is%@", Key];if ([mArray containsObject:_key]) {// 4.2 獲取相應的 ivarIvar ivar = class_getInstanceVariable([self class], _key.UTF8String);// 4.3 對相應的 ivar 設置值object_setIvar(self, ivar, value);return;}else if ([mArray containsObject:_isKey]) {Ivar ivar = class_getInstanceVariable([self class], _isKey.UTF8String);object_setIvar(self, ivar, value);return;}else if ([mArray containsObject:key]) {Ivar ivar = class_getInstanceVariable([self class], key.UTF8String);object_setIvar(self, ivar, value);return;}else if ([mArray containsObject:isKey]) {Ivar ivar = class_getInstanceVariable([self class], isKey.UTF8String);object_setIvar(self, ivar, value);return;}// 5、如果找不到則拋出異常@throw [NSException exceptionWithName:@"GCUnknownKeyException" reason:[NSString stringWithFormat:@"****[%@ %@]: this class is not key value coding-compliant for the key name.****",self,NSStringFromSelector(_cmd)] userInfo:nil];
}// 獲取實例變量名列表
- (NSMutableArray *)getIvarListName {NSMutableArray *mArray = [NSMutableArray arrayWithCapacity:1];unsigned int count = 0;Ivar *ivars = class_copyIvarList([self class], &count);for (int i = 0; i < count; i++) {Ivar ivar = ivars[i];const char *ivarNameChar = ivar_getName(ivar);NSString *ivarName = [NSString stringWithUTF8String:ivarNameChar];[mArray addObject:ivarName];}free(ivars);return mArray;
}@end

取值

取值的自定義代碼如下,分為以下幾步

  • 1、判斷key非空
  • 2、查找相應方法,順序是:get<Key>、 <key>、 countOf<Key>、 objectIn<Key>AtIndex
  • 3、判斷是否能夠直接賦值實例變量,即判斷是否響應accessInstanceVariablesDirectly方法,間接訪問實例變量,
    • 返回YES,繼續下一步取值
    • 如果是NO,則崩潰
  • 4、間接訪問實例變量,順序是:_<key> _is<Key> <key> is<Key>
    • 4.1 定義一個收集實例變量的可變數組
    • 4.2 通過class_getInstanceVariable方法,獲取相應的 ivar
    • 4.3 通過object_getIvar方法,返回相應的 ivar 的值
// 取值
- (nullable id)gc_valueForKey:(NSString *)key {// 1、判斷非空if (key == nil || key.length == 0) {return nil;}// 2、找到相關方法:get<Key> <key> countOf<Key> objectIn<Key>AtIndex// key 要大寫//capitalizedString 會將每個單詞的首字母大寫,其余小寫。//例如:key = @"firstName" → capitalizedString 后為 @"FirstName" → 方法名 getFirstName。但是URL會變成UrlNSString *Key = key.capitalizedString;// 拼接方法NSString *getKey = [NSString stringWithFormat:@"get%@", Key];NSString *countOfKey = [NSString stringWithFormat:@"countOf%@", Key];NSString *objectInKeyAtIndex = [NSString stringWithFormat:@"objectIn%@AtIndex:", Key];#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"if ([self respondsToSelector:NSSelectorFromString(getKey)]) {return [self performSelector:NSSelectorFromString(getKey)];} else if ([self respondsToSelector:NSSelectorFromString(key)]) {return [self performSelector:NSSelectorFromString(key)];}// 集合類型else if ([self respondsToSelector:NSSelectorFromString(countOfKey)]) {if ([self respondsToSelector:NSSelectorFromString(objectInKeyAtIndex)]) {int num = (int)[self performSelector:NSSelectorFromString(countOfKey)];NSMutableArray *mArray = [NSMutableArray arrayWithCapacity:1];for (int i = 0; i < num - 1; i++) {num = (int)[self performSelector:NSSelectorFromString(countOfKey)];}for (int j = 0; j < num; j++) {id objc = [self performSelector:NSSelectorFromString(objectInKeyAtIndex) withObject:@(j)];[mArray addObject:objc];}return mArray;}}
#pragma clang diagnostic pop// 3、判斷是否響應 `accessInstanceVariablesDirectly` 方法if (![self.class accessInstanceVariablesDirectly]) {@throw [NSException exceptionWithName:@"GCUnKnownKeyException" reason:[NSString stringWithFormat:@"****[%@ valueForUndefinedKey:]: this class is not key value coding-compliant for the key name.****", self] userInfo:nil];}// 4. 找相關實例變量進行取值,順序為:_<key>、_is<Key>、<key>、is<Key>NSMutableArray *mArray = [self getIvarListName];NSString *_key = [NSString stringWithFormat:@"_%@", key];NSString *_isKey = [NSString stringWithFormat:@"_is%@", Key];NSString *isKey = [NSString stringWithFormat:@"is%@", Key];if ([mArray containsObject:_key]) {Ivar ivar = class_getInstanceVariable([self class], _key.UTF8String);return object_getIvar(self, ivar);} else if ([mArray containsObject:_isKey]) {Ivar ivar = class_getInstanceVariable([self class], _isKey.UTF8String);return object_getIvar(self, ivar);} else if ([mArray containsObject:key]) {Ivar ivar = class_getInstanceVariable([self class], key.UTF8String);return object_getIvar(self, ivar);} else if ([mArray containsObject:isKey]) {Ivar ivar = class_getInstanceVariable([self class], isKey.UTF8String);return object_getIvar(self, ivar);}return @"";
}

特性:無隱私訪問

KVC 可訪問私有屬性(突破 @private/@protected 限制):

// Person.h
@interface Person : NSObject {@privateNSString *_secretCode; // 私有實例變量
}@property (nonatomic, copy) NSString *publicName; // 公開屬性
@end// Person.m
@implementation Person
// 不暴露 _secretCode 的任何方法
@end

通過KVC強制訪問私有屬性

// 創建一個對象
Person *person = [[Person alloc] init];// 合法操作:通過屬性訪問公開字段
person.publicName = @"Alice";// 非法操作(編譯器會報錯):直接訪問私有變量
// person->_secretCode = @"123"; //  編譯錯誤:'secretCode' is private// 但通過 KVC 可以繞過限制
[person setValue:@"TOP_SECRET_123" forKey:@"secretCode"]; // 讀取私有變量
NSString *stolenSecret = [person valueForKey:@"secretCode"];
NSLog(@"竊取的私有變量值: %@", stolenSecret); 
// 輸出:竊取的私有變量值: TOP_SECRET_123
原理

KVC 查找順序

  • 先嘗試調用 setSecretCode:_setSecretCode: 方法(不存在)。
  • 然后直接訪問實例變量 _secretCode(即使它是 @private)。

如果需要保護私有屬性,可重寫 accessInstanceVariablesDirectly 返回 NO

四、多元應用場景

1. 動態數據處理

(1)字典轉模型
// 模型類
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@end// 批量賦值
NSDictionary *data = @{@"name": @"Alice", @"age": @25};
Person *person = [[Person alloc] init];
[person setValuesForKeysWithDictionary:data]; // KVC 批量賦值
(2)模型轉字典
NSDictionary *dict = [person dictionaryWithValuesForKeys:@[@"name", @"age"]]; // KVC 提取屬性值

2. 系統控件定制

修改 UITextField 占位符顏色(私有屬性 _placeholderLabel):

UITextField *textField = [[UITextField alloc] init];
UILabel *placeholderLabel = [textField valueForKey:@"_placeholderLabel"];
placeholderLabel.textColor = [UIColor lightGrayColor]; // 通過 KVC 修改私有屬性

3. 高階集合操作

在對容器類使用KVC時,valueForKey:將會被傳遞給容器中的每一個對象,而不是對容器本身進行操作,結果會被添加到返回的容器中,這樣,可以很方便的操作集合 來返回 另一個集合(如:首字母大寫):

NSArray *arr = @[@"hello", @"world"];
NSArray *capitalizedArr = [arr valueForKey:@"capitalizedString"]; // 結果:@[@"Hello", @"World"]

有如下Person類

@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, assign) CGFloat salary;
@end// 數據準備
NSArray *people = @[[Person personWithName:@"Alice" age:25 salary:5000],[Person personWithName:@"Bob" age:30 salary:8000],[Person personWithName:@"Charlie" age:28 salary:6000]
];

(1) 聚合運算

操作符作用示例
@count返回集合元素個數[people valueForKeyPath:@"@count"]3
@sum求和[people valueForKeyPath:@"@sum.age"]83
@avg平均值[people valueForKeyPath:@"@avg.salary"]6333.33
@max最大值[people valueForKeyPath:@"@max.age"]30
@min最小值[people valueForKeyPath:@"@min.salary"]5000

(2) 數組映射

操作符作用示例
@unionOfObjects提取屬性組成新數組(不去重)[people valueForKeyPath:@"@unionOfObjects.name"]["Alice", "Bob", "Charlie"]
@distinctUnionOfObjects提取屬性并去重若兩人同名,結果會去重

(3) 嵌套集合操作

如果集合中嵌套集合(如 NSArray<NSArray *>):

NSArray *departments = @[@[person1, person2], @[person3, person4]
];
// 提取所有員工的 name(扁平化)
NSArray *allNames = [departments valueForKeyPath:@"@unionOfArrays.name"];

當然我們還可以通過自定義方法來實現自定義操作

@implementation Person// 自定義 KVC 集合操作符
- (id)valueForKeyPath:(NSString *)keyPath {if ([keyPath hasSuffix:@"@median"]) {NSArray *values = [self valueForKeyPath:[keyPath substringToIndex:keyPath.length - 7]];return [self medianOfArray:values];}return [super valueForKeyPath:keyPath];
}- (NSNumber *)medianOfArray:(NSArray *)numbers {// 計算中位數邏輯...
}@end// 使用
NSNumber *medianAge = [people valueForKeyPath:@"age@median"];

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/90400.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/90400.shtml
英文地址,請注明出處:http://en.pswp.cn/web/90400.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Lucene】leafreadercontext邏輯段與segment物理磁盤段的關系

在 Lucene 中&#xff0c;“葉子段”&#xff08;LeafReaderContext&#xff09;和 “segment”&#xff08;物理段&#xff09;在 Lucene 語境下&#xff0c;LeafReaderContext ≈ segment 的運行時只讀視圖。概念 所在層次 含義 是否一一對應 segment 物理存儲層 Lucene 索引…

Python進階第三方庫之Matplotlib

應用Matplotlib的基本功能實現圖形顯示 應用Matplotlib實現多圖顯示 應用Matplotlib實現不同畫圖種類 1、什么是Matplotlib是專門用于開發2D圖表(包括3D圖表) 以漸進、交互式方式實現數據可視化 2、為什么要學習Matplotlib可視化是在整個數據挖掘的關鍵輔助工具&#xff0c;可以…

【深度解析】從AWS re_Invent 2025看云原生技術發展趨勢

2025 年 6 月 28 日 在科技浪潮持續翻涌的當下&#xff0c;云原生技術已然成為推動企業數字化轉型與創新發展的關鍵力量。而 AWS re:Invent 作為云計算領域一年一度的盛會&#xff0c;向來是展示前沿技術、洞察行業趨勢的重要舞臺。在今年的 AWS re:Invent 2025 大會上&#xf…

高亮標題里的某個關鍵字正則表達式

使用v-html渲染&#xff0c;寫一個高亮方法<span class"title-name" v-html"highlightKeywords(name, keywords)"></span>這里傳入的name帶了文件拓展名&#xff0c;所以先把名稱從文件名里提取出來// 高亮標題顏色highlightKeywords(name, ke…

視頻編解碼中colorspace,color_range,color_trc,color_primaries,是做什么用的,是誰來指定的

在視頻編解碼中&#xff0c;colorspace&#xff08;色彩空間&#xff09;、color_range&#xff08;色域范圍&#xff09;、color_trc&#xff08;傳輸特性&#xff09;、color_primaries&#xff08;原色&#xff09;是一組色彩相關元數據&#xff0c;它們共同決定了視頻的顏色…

【QT】 Qt背景介紹與概述

文章目錄&#x1f4dd;Qt背景介紹&#x1f320; 什么是Qt&#x1f309;Qt的發展史&#x1f320; Qt?持的平臺&#x1f309; Qt版本&#x1f309; Qt的優點&#x1f309; Qt的應?場景&#x1f320; Qt的成功案例&#x1f320; Qt的發展前景及就業分析&#x1f6a9;總結&#x…

如何將擁有的域名自定義鏈接到我的世界服務器(Minecraft服務器)

關于Dynadot Dynadot是通過ICANN認證的域名注冊商&#xff0c;自2002年成立以來&#xff0c;服務于全球108個國家和地區的客戶&#xff0c;為數以萬計的客戶提供簡潔&#xff0c;優惠&#xff0c;安全的域名注冊以及管理服務。 Dynadot平臺操作教程索引&#xff08;包括域名郵…

2025暑期—07深度學習應用-總結

人有自動選取卷積核的能力&#xff0c;傳統的圖像處理不能自動選取卷積核非線性作用函數&#xff0c;Sigmoid由于梯度消失使用Relu。卷積神經網絡的卷積核是未知的&#xff0c;自適應的。其中的權重是不斷變化的&#xff0c;就是卷積核是不斷變化的。卷積模糊了&#xff0c;池化…

數據結構-4(常用排序算法、二分查找)

一、思維導圖二、冒泡排序def bubble_sort(ls):"""用i循環,逐步比較相鄰元素,直到循環結束,停止交換&#xff0c;就像一個個氣泡從下往上冒泡,每一次的循環結果都是最大的元素到了后面已排序序列的列首。"""j 0 # 用于確定循環次數,同時用于下…

策略模式(Strategy Pattern)+ 模板方法模式(Template Method Pattern)的組合使用

using Microsoft.Extensions.DependencyInjection;namespace ConsoleApp9 {internal class Program{static async Task Main(string[] args){Console.WriteLine("Hello, World!");// 創建并配置依賴注入容器var _serviceProvider new ServiceCollection().AddScoped…

es0102---語法格式、數據類型、整合springboot、創建庫、創建映射、新增數據、自定義查詢

ES 一、創建映射字段的語法格式 需要先構建索引庫&#xff0c;在構建索引庫中的映射關系 PUT /索引庫名/_mapping {"properties": {"字段名": {"type": "類型","index": true&#xff0c;"store": false&#…

spring boot h2數據庫無法鏈接問題

spring boot h2數據庫無法鏈接問題datasource:# 數據庫連接地址&#xff1a;H2在2.x后&#xff0c;不再支持創建數據庫&#xff0c;需要手工創建&#xff0c;如&#xff1a;touch test.mv.db&#xff0c;# 否則會報“Database file not found”錯誤url: jdbc:h2:file:~/testdri…

pycharm配conda環境

最近在做表情包&#xff0c;畫出來的表情包大小不一&#xff0c;但是vx表情包平臺要求統一都是240*240的&#xff0c;所以用Pillow統一處理的一下。 如果你本地裝的python并且添加到path了&#xff0c;pycharm可以自動獲取到&#xff0c;但是我裝得miniconda&#xff0c;pychar…

【Elasticsearch】Elasticsearch 跨機房部署

《Elasticsearch 集群》系列&#xff0c;共包含以下文章&#xff1a; 1?? 冷熱集群架構2?? 合適的鍋炒合適的菜&#xff1a;性能與成本平衡原理公式解析3?? ILM&#xff08;Index Lifecycle Management&#xff09;策略詳解4?? Elasticsearch 跨機房部署5?? 快照與恢…

立式數控深孔鉆的工藝及光學檢測方法 —— 激光頻率梳 3D 輪廓檢測

引言立式數控深孔鉆作為深孔加工的關鍵設備&#xff0c;其工藝水平直接影響零件加工質量。深孔加工面臨排屑、散熱等挑戰&#xff0c;而光學檢測技術的發展為深孔加工精度控制提供了新途徑。激光頻率梳 3D 輪廓檢測技術與立式數控深孔鉆工藝的結合&#xff0c;實現了深孔加工與…

【YOLO系列】YOLOv4詳解:模型結構、損失函數、訓練方法及代碼實現

YOLOv4詳解&#xff1a;模型結構、損失函數、訓練方法及代碼實現 motivation YOLO系列作者Joseph Redmon與Alexey Bochkovskiy致力于解決目標檢測領域的核心矛盾&#xff1a;精度與速度的平衡。YOLOv4的誕生源于兩大需求&#xff1a; 工業落地&#xff1a;在移動端/邊緣設備…

chromedriver下載與安裝方法

chromedriver下載地址&#xff1a; 版本在&#xff1a;http://chromedriver.storage.googleapis.com/index.html 這是下載后&#xff1a; 把exe文件復制到瀏覽器的安裝目錄下 把exe文件復制到python的安裝目錄下 配置環境變量:此電腦→右擊屬性→高級系統設置→環境變量→用戶…

基于QT(C++)實現(圖形界面)選課管理系統

選課管理系統1 概述1.1 課程設計目的和意義根據課程大綱設定&#xff0c;面向對象課程設計的目的是&#xff1a;&#xff08;1&#xff09;理解面向對象的基本思想和三大機制&#xff0c;掌握基于 C 語法的面向對象的基 本概念和開發模式&#xff0c;熟練運用面向對象思維模式…

【阿里云-ACP-1】疑難題解析

1.彈性伸縮 AS 在企業中有廣泛的應用場景,不僅適合業務量不斷波動的應用程序,同時也適合業務量穩定的應用程序。以下關于彈性伸縮的使用說法正確的是( ) 選項內容 A 彈性伸縮可以用于云數據庫 RDS 的自動擴容 B 彈性伸縮支持自動將 ECS 實例或 ECI 實例添加到 Memcache 實…

NLP:seqtoseq英譯法案例

本文目錄&#xff1a;一、案例概述二、數據集三、案例步驟&#xff08;一&#xff09;導入工具包和工具函數&#xff08;二&#xff09;數據預處理&#xff08;三&#xff09;構建數據源對象&#xff08;四&#xff09;構建數據迭代器&#xff08;五&#xff09;構建基于GRU的編…