Python-VBA函數之旅-setattr函數

目錄

一、setattr函數的常見應用場景

二、setattr函數使用注意事項

三、如何用好setattr函數?

1、setattr函數:

1-1、Python:

1-2、VBA:

2、推薦閱讀:

個人主頁:?https://blog.csdn.net/ygb_1024?spm=1010.2135.3001.5421

一、setattr函數的常見應用場景

????????setattr函數在Python中有廣泛的應用場景,特別是在動態實現類屬性或方法、元編程(metaprogramming)以及處理對象時不知道具體屬性名的情況下,常見的應用場景有:

1、動態實現類屬性或方法:當你不確定類的所有屬性或方法時,可以在運行時使用setattr()函數動態地添加它們,這可以用于創建可擴展的類,或者根據外部配置動態地添加功能。

2、簡化對象屬性的批量設置:如果你有一個對象,并且需要從字典或其他數據源中設置多個屬性,setattr()函數可以幫助你簡化這個過程。

3、實現代理對象或裝飾器:在代理對象或裝飾器模式中,你可能需要攔截對某個對象的屬性訪問,并在訪問之前或之后執行一些操作,你可以使用setattr()函數來動態地修改被代理對象的屬性。

4、結合描述符(Descriptors)使用:描述符是Python中一個強大的特性,允許你控制對對象屬性的訪問,當描述符與setattr()函數結合使用時,你可以實現更復雜的屬性訪問邏輯。

5、序列化和反序列化:在處理自定義對象的序列化和反序列化時,setattr()函數可以幫助你根據序列化的數據動態地設置對象的屬性,這在處理JSON、XML或其他格式的數據時特別有用。

6、元編程:在元編程中,你編寫操作其他代碼的代碼,setattr()函數允許你動態地修改對象的結構,這在創建代理、裝飾器、元類等高級編程概念時非常有用。

7、處理用戶輸入:如果你正在編寫一個接受用戶輸入并動態設置對象屬性的程序,setattr()函數可以幫助你根據用戶輸入來設置屬性。

????????注意,過度使用setattr()函數可能會使代碼難以理解和維護,因為它破壞了對象的明確性和封裝性,因此,在使用setattr()函數時應該謹慎,并確保你的代碼清晰、可讀和可維護。

二、setattr函數使用注意事項

????????在Python中,setattr()是一個內置函數,用于設置對象的屬性值,它的基本用法是setattr(object, name, value),其中,object是你想要修改其屬性的對象,name是屬性的名稱(作為一個字符串),而value是你想要設置的新值。

在使用setattr()函數時,需注意以下事項:

1、屬性名稱作為字符串:name參數必須是一個字符串,它指定了你想要設置的屬性的名稱,如果你嘗試使用一個非字符串值,Python會拋出一個TypeError異常。
2、不存在的屬性:如果對象沒有名為name的屬性,setattr()會創建一個新的屬性,但是,如果你試圖設置一個只讀屬性(如某些內置類型或擴展類型中的屬性),可能會引發異常。
3、隱藏或覆蓋內置方法:如果你使用setattr()函數設置了一個與對象現有方法同名的屬性,那么這個方法將被該屬性隱藏或覆蓋,這可能會導致意外的行為,特別是如果后來你嘗試調用那個方法但忘記了已經被覆蓋。
4、動態屬性:雖然setattr()函數允許你動態地設置對象的屬性,但這并不意味著你應該濫用它,過度使用動態屬性可能會使代碼難以理解和維護,在可能的情況下,最好明確地在類定義中聲明屬性。
5、安全性:setattr()函數可以被用于修改對象的任何屬性,包括私有屬性(在Python中,以雙下劃線開頭的屬性名稱被認為是私有的),這可能會破壞對象的內部狀態,并導致不可預測的行為,因此,在使用setattr()函數時,你應該非常小心,確保你只修改你真正想要修改的屬性。
6、異常處理:在設置屬性時,可能會發生各種異常,如AttributeError(如果嘗試訪問不存在的屬性)或TypeError(如果屬性類型與賦值不兼容),你應該準備好處理這些異常,以防止程序崩潰。
7、性能:雖然setattr()函數在大多數情況下都足夠快,但在某些情況下,頻繁地使用它可能會導致性能問題,如果你需要頻繁地設置大量屬性,可能需要考慮其他更高效的方法。
8、結合getattr()/delattr()使用:getattr()/delattr()是另外兩個與setattr()相關的內置函數,它們分別用于獲取和刪除對象的屬性,在編寫處理對象屬性的代碼時,這三個函數通常會一起使用。

三、如何用好setattr函數?

????????要在Python中妥善使用setattr()函數,你需遵循以下建議:

1、明確目的:首先,確定你為何需要使用setattr()函數?在大多數情況下,直接在類定義中聲明屬性或使用常規的賦值語法是更簡單、更直觀的選擇,如果你確實需要動態地設置屬性,那么setattr()函數是一個有用的工具。

2、避免覆蓋內置方法:在調用setattr()函數時,確保你沒有意外地覆蓋對象的內置方法或屬性,你可以通過檢查name參數的值來避免這種情況。

3、考慮封裝:如果你經常需要動態地設置屬性,可以考慮將setattr()的調用封裝到一個類或方法中,這樣可以隱藏底層復雜性,并提供一個更清晰的接口給調用者。

4、使用字典代替屬性:如果你需要存儲大量的動態屬性,并且不關心它們作為對象的屬性暴露給外部代碼,那么使用字典來存儲這些屬性可能是一個更好的選擇。字典提供了靈活的鍵值對存儲,并且你可以使用dict.get(), dict.setdefault()?和dict.update()等方法來操作它們。

5、處理異常:當使用setattr()函數時,要準備好處理可能發生的異常,如AttributeError(如果嘗試訪問不存在的屬性)或TypeError(如果賦值類型不兼容),你可以使用try/except塊來捕獲這些異常,并相應地處理它們。

6、文檔化:如果你在你的代碼中使用setattr()函數,確保在相關的文檔或注釋中解釋清楚它的用途和潛在的影響,這可以幫助其他開發者更好地理解你的代碼,并避免意外的副作用。

7、測試:編寫測試用例來驗證你使用setattr()函數的代碼的正確性。確保你的測試覆蓋了各種情況,包括正常情況和異常情況,這可以幫助你發現潛在的問題,并確保你的代碼在所有預期的情況下都能正常工作。

8、謹慎使用:盡管setattr()函數在某些情況下很有用,但它也可能導致代碼難以理解和維護,因此,你應該謹慎地使用它,并確保你的代碼在不需要動態屬性時仍然能夠正常工作。

1、setattr函數:
1-1、Python:
# 1.函數:setattr
# 2.功能:用于設置對象的屬性值
# 3.語法:setattr(object, name, value)
# 4.參數:
# 4-1、object:對象
# 4-2、name:字符串,表示對象屬性
# 4-3、value:屬性值
# 5.返回值:無
# 6.說明:
# 7.示例:
# 用dir()函數獲取該函數內置的屬性和方法
print(dir(setattr))
# ['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
# '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__name__',
# '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__',
# '__str__', '__subclasshook__', '__text_signature__']# 用help()函數獲取該函數的文檔信息
help(setattr)# 應用一:動態實現類屬性或方法
# 示例1:動態設置類實例的屬性
class MyClass:def __init__(self):self.existing_attribute = 'I exist!'
# 創建一個類的實例
instance = MyClass()
# 使用setattr()動態地添加一個屬性
setattr(instance, 'my_weight', '70.6kg')
# 訪問動態添加的屬性
print(instance.my_weight)
# 70.6kg# 示例2:動態設置類的方法
class MyClass:def existing_method(self):print('I am an existing method!')
# 創建一個類的實例
instance = MyClass()
# 定義一個要動態添加的方法
def dynamic_method(self):print('I am a dynamically added method!')
# 使用setattr()動態地添加一個方法
setattr(MyClass, 'dynamic_method', dynamic_method)
# 在類的實例上調用動態添加的方法(注意:我們是在類上添加的方法,所以所有實例都可以訪問)
instance.dynamic_method()
# I am a dynamically added method!# 示例3:動態設置類的屬性(即類變量)
class MyClass:existing_class_variable = 'I am a class variable!'
# 使用setattr()動態地添加一個類變量
setattr(MyClass, 'dynamic_class_variable', 'I was dynamically added as a class variable!')
# 訪問動態添加的類變量(通過類本身或其實例)
print(MyClass.dynamic_class_variable)  # 輸出: I was dynamically added as a class variable!
print(MyClass().dynamic_class_variable)  # 同樣輸出: I was dynamically added as a class variable!
# I was dynamically added as a class variable!
# I was dynamically added as a class variable!# 應用二:簡化對象屬性的批量設置
class Person:def __init__(self):self.name = Noneself.age = Noneself.city = None
# 創建一個Person實例
person = Person()
# 使用字典來存儲要設置的屬性值
attributes = {'name': 'Myelsa','age': 18,'city': 'Guangzhou'
}
# 使用setattr()批量設置屬性
for key, value in attributes.items():setattr(person, key, value)
# 驗證屬性是否設置成功
print(person.name)
print(person.age)
print(person.city)
# Myelsa
# 18
# Guangzhou# 應用三:實現代理對象或裝飾器
class Proxy:def __init__(self, obj):self._obj = objdef __setattr__(self, name, value):# 檢查是否是要攔截的屬性if name.startswith('_'):# 如果以'_'開頭,則直接設置到代理對象本身super().__setattr__(name, value)else:# 否則,攔截對_obj屬性的設置,并可能添加一些額外的邏輯print(f"Intercepted setattr for {name}. Original value: {getattr(self._obj, name, 'None')}")# 在這里可以添加一些邏輯,比如驗證、轉換等# ...# 設置值到_objsetattr(self._obj, name, value)print(f"Set {name} to {value} in the original object.")def __getattr__(self, name):# 如果訪問的屬性不存在于代理對象本身,則轉發到_objreturn getattr(self._obj, name)
class MyClass:def __init__(self):self.x = 10
# 創建一個MyClass實例和一個代理對象
obj = MyClass()
proxy = Proxy(obj)
# 嘗試設置代理對象的屬性
proxy.x = 20
# 嘗試訪問代理對象的屬性
print(proxy.x)
# Intercepted setattr for x. Original value: 10
# Set x to 20 in the original object.
# 20# 應用四:結合描述符(Descriptors)使用
class BoundedDescriptor:def __init__(self, name, lower=None, upper=None):self.name = nameself.lower = lowerself.upper = upperself._value = Nonedef __get__(self, instance, owner):if instance is None:return selfreturn self._valuedef __set__(self, instance, value):if self.lower is not None and value < self.lower:raise ValueError(f"{self.name} must be greater than or equal to {self.lower}")if self.upper is not None and value > self.upper:raise ValueError(f"{self.name} must be less than or equal to {self.upper}")self._value = valueprint(f"Setting {self.name} to {value}")def __delete__(self, instance):raise AttributeError("Cannot delete the descriptor")
class MyClass:x = BoundedDescriptor('x', 0, 10)
# 創建一個MyClass的實例
obj = MyClass()
# 使用setattr()設置屬性(這實際上是調用描述符的__set__方法)
setattr(obj, 'x', 5)  # 輸出: Setting x to 5
print(obj.x)  # 輸出: 5
# 嘗試設置一個超出范圍的值
try:setattr(obj, 'x', -1)
except ValueError as e:print(e)  # 輸出: x must be greater than or equal to 0
# 嘗試刪除描述符(會引發異常)
try:delattr(obj, 'x')
except AttributeError as e:print(e)  # 輸出: Cannot delete the descriptor
# Setting x to 5
# 5
# x must be greater than or equal to 0
# Cannot delete the descriptor# 應用五:序列化和反序列化
class Person:def __init__(self, name, age):self.name = nameself.age = agedef __repr__(self):return f"Person(name={self.name}, age={self.age})"
def serialize_person(person):"""將Person對象序列化為字典"""return {'name': person.name,'age': person.age}
def deserialize_person(data):"""從字典反序列化為Person對象"""person = Person(None, None)  # 創建一個空的Person對象for key, value in data.items():setattr(person, key, value)  # 使用setattr()設置屬性return person
# 示例用法
# 序列化
person = Person("Myelsa", 18)
serialized_data = serialize_person(person)
print(serialized_data)
# 反序列化
deserialized_person = deserialize_person(serialized_data)
print(deserialized_person)
# {'name': 'Myelsa', 'age': 18}
# Person(name=Myelsa, age=18)# 應用六:元編程
class DynamicClass:def __init__(self):# 用于存儲動態方法的字典self._dynamic_methods = {}def add_method(self, name, func):"""動態地添加一個方法到類中"""setattr(self, name, func)# 同時將方法存儲在字典中以便后續可能的操作self._dynamic_methods[name] = funcdef remove_method(self, name):"""動態地移除一個方法"""if hasattr(self, name):delattr(self, name)if name in self._dynamic_methods:del self._dynamic_methods[name]def list_methods(self):"""列出所有的動態方法(不包括內置方法)"""return list(self._dynamic_methods.keys())
# 示例函數
def hello_world():print("Hello, world!")
def greet(name):print(f"Hello, {name}!")
# 創建一個DynamicClass的實例
dynamic_instance = DynamicClass()
# 動態地添加一個方法
dynamic_instance.add_method('hello', hello_world)
# 調用動態添加的方法
dynamic_instance.hello()  # 輸出: Hello, world!
# 列出所有的動態方法
print(dynamic_instance.list_methods())  # 輸出: ['hello']
# 動態地添加另一個方法,這次使用lambda表達式
dynamic_instance.add_method('greet_by_name', lambda name: greet(name))
# 調用通過lambda添加的方法
dynamic_instance.greet_by_name('Myelsa')  # 輸出: Hello, Myelsa!
# 移除一個方法
dynamic_instance.remove_method('hello')
# 再次列出所有的動態方法
print(dynamic_instance.list_methods())  # 輸出: ['greet_by_name']
# 嘗試調用已被移除的方法
# dynamic_instance.hello()  # 這將引發 AttributeError
# Hello, world!
# ['hello']
# Hello, Myelsa!
# ['greet_by_name']# 應用七:處理用戶輸入
class UserDefinedAttributes:def __init__(self):# 初始化一個空字典來存儲用戶定義的屬性self._user_attributes = {}def set_attribute(self, name, value):# 檢查屬性名是否以"user_"開頭,以限制可設置的屬性范圍if name.startswith("user_"):# 使用setattr()來設置屬性setattr(self, name, value)# 同時將屬性存儲在字典中,以便后續可能的操作或檢查self._user_attributes[name] = valueprint(f"Attribute {name} set to {value}")else:print(f"Error: Cannot set attribute {name}. Only attributes starting with 'user_' are allowed.")def get_attribute(self, name):# 檢查屬性是否存在if hasattr(self, name):return getattr(self, name)else:print(f"Error: Attribute {name} does not exist.")return Nonedef list_attributes(self):# 列出所有用戶定義的屬性return list(self._user_attributes.keys())
# 示例用法
obj = UserDefinedAttributes()
# 獲取用戶輸入
name = input("Enter attribute name (must start with 'user_'): ")
value = input("Enter attribute value: ")
# 嘗試設置屬性
obj.set_attribute(name, value)
# 列出所有用戶定義的屬性
print("User defined attributes:")
for attr in obj.list_attributes():print(f"{attr}: {obj.get_attribute(attr)}")
# 嘗試獲取并打印一個屬性
attr_to_get = input("Enter attribute name to get (or 'exit' to quit): ")
if attr_to_get.lower() != 'exit':print(f"Value of {attr_to_get}: {obj.get_attribute(attr_to_get)}")
else:print("Exiting...")
1-2、VBA:
略,待后補。
2、推薦閱讀:

2-1、Python-VBA函數之旅-round()函數

Python算法之旅:Algorithm

Python函數之旅:Functions

個人主頁:?神奇夜光杯-CSDN博客

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

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

相關文章

宏集Panorama SCADA軟件獲BACnet BTL認證

Panorama 獲得BACnet BTL認證 建筑物的組件&#xff08;空調系統、照明傳感器等&#xff09;能否使用共同通訊協議&#xff1f;這正是標準化 BACnet協議&#xff08;Building Automation and Control Networks&#xff09;所提供的功能。該協議旨在實現建筑物中各種設備和系統…

【TS】入門

創建項目 vscode自動編譯ts 生成配置文件 tsc --init 然后發現終端也改變了&#xff1a;

SOCKET編程(3):相關結構體與函數

相關結構體與函數 sockaddr、sockaddr_in結構體 sockaddr和sockaddr_in詳解 struct sockaddr共16字節&#xff0c;協議族(family)占2字節&#xff0c;IP地址和端口號在sa_data字符數組中 /* Structure describing a generic socket address. */ struct sockaddr {__SOCKADDR…

抓大鵝教程電腦端秒通關……

大家好&#xff0c;我是小黃。 最近抓大鵝小程序游戲很火&#xff0c;抓大鵝小游戲是由青島藍飛互娛科技股份有限公司開發并推出的一款休閑益智類三消游戲。在游戲中&#xff0c;玩家需要在特定的“購物籃子”背景下&#xff0c;找到三個相同的物品并將其消除。游戲的玩法簡單…

社工庫信息查詢

此網站需要注冊賬號&#xff0c;新用戶注冊送3點券&#xff0c;每日簽到可獲得1.5點券。也可通過充值來查 我這里有方法可以利用缺陷來無限獲取點券查人

Python 實戰之量化交易

1. Python 實戰之量化交易 2..Python量化交易實戰-04.量化交易系統架構的設計 Python量化交易實戰-04.量化交易系統架構的設計 - 知乎 3.Python量化交易實戰-06.通過PythonAPI獲取股票數據 Python量化交易實戰-06.通過PythonAPI獲取股票數據 - 知乎 3.Python量化交易實戰…

程序員的歸宿。。

大家好&#xff0c;我是瑤琴呀。 相信每個進入職場的人都考慮過自己的職業生涯規劃&#xff0c;在不同的年齡段可能面臨不同挑戰&#xff0c;這點對于 35 的人應該更為感同身受。 對于程序員來說&#xff0c;大部分人的職業道路主要是下面三種&#xff1a;第一條&#xff0c;…

【Delphi 爬蟲庫 6】使用正則表達式提取貓眼電影排行榜top100

正則表達式庫的簡單介紹 正則表達式易于使用&#xff0c;功能強大&#xff0c;可用于復雜的搜索和替換以及基于模板的文本檢查。這對于輸入形式的用戶輸入驗證特別有用-驗證電子郵件地址等。您還可以從網頁或文檔中提取電話號碼&#xff0c;郵政編碼等&#xff0c;在日志文件中…

人生是曠野,不是軌道

最近看到一句話&#xff0c;很喜歡&#xff0c;分享一下。"人生是曠野&#xff0c;不是軌道"。人生不是固定的方程式&#xff0c;也沒有唯一答案&#xff0c;沒有誰生來就應該是什么樣。別太被太多世俗觀念束縛住手腳&#xff0c;每個人都有權利自由生長&#xff0c;…

用友暢捷通T+ keyEdit sql注入漏洞

產品介紹 暢捷通 T 是一款靈動&#xff0c;智慧&#xff0c;時尚的基于互聯網時代開發的管理軟件&#xff0c;主要針對中小型工貿與商貿企業&#xff0c;尤其適合有異地多組織機構&#xff08;多工廠&#xff0c;多倉庫&#xff0c;多辦事處&#xff0c;多經銷商&#xff09;的…

朋友圈刷屏的粘土風格照片,你體驗過了嗎?

Remini 的粘土風格真的丑萌丑萌的&#xff01; 從去年“妙鴨相機”的走紅&#xff0c;到今年Remini的刷屏&#xff0c;其實可以看出大眾對于圖片趣玩的興趣非常大&#xff01; 一張普通的照片經過工具的處理&#xff0c;一下子變成新風格&#xff0c;讓人眼前一亮。如果你也對…

GPT-SoVits:語音克隆,語音融合

首發網站 https://tianfeng.space 前言 零樣本文本到語音&#xff08;TTS&#xff09;&#xff1a; 輸入 5 秒的聲音樣本&#xff0c;即刻體驗文本到語音轉換。少樣本 TTS&#xff1a; 僅需 1 分鐘的訓練數據即可微調模型&#xff0c;提升聲音相似度和真實感。跨語言支持&…

信息收集方法合集 第1期

前言 在工作中&#xff0c;經常被問到某個文件怎么下載&#xff0c;原文來自哪里。索性把我知道的所有信息收集方法全部整理一遍&#xff0c;希望對大家有用&#xff0c;如果有幫助到你&#xff0c;非常榮幸&#xff0c;我會堅持分享我的學習、工作經驗。 信息種類&#xff1…

如何用java編寫一個猜數字游戲

我想到用c能編出一個猜數字游戲&#xff0c;于是我就嘗試用java編寫一個 代碼如下&#xff1a; import java.util.Scanner; import java.util.Random;public class GuessTheNumber {public static void main(String[] args) {Scanner scanner new Scanner(System.in);Random…

云啟未來:“云計算與網絡運維精英交流群”與“獨家資料”等你來探索“

作者簡介&#xff1a;一名云計算網絡運維人員、每天分享網絡與運維的技術與干貨。 公眾號&#xff1a;網絡豆云計算學堂 座右銘&#xff1a;低頭趕路&#xff0c;敬事如儀 個人主頁&#xff1a; 網絡豆的主頁????? &#x1f680; 云計算與運維精英交流群誠邀您的加入…

搭建Docker私服鏡像倉庫Harbor

1、概述 Harbor是由VMware公司開源的企業級的Docker Registry管理項目&#xff0c;它包括權限管理(RBAC)、LDAP、日志審核、管理界面、自我注冊、鏡像復制和中文支持等功能。 Harbor 的所有組件都在 Dcoker 中部署&#xff0c;所以 Harbor 可使用 Docker Compose 快速部署。 …

PermissionError: [Errno 13] Permission denied: ‘xx.xlsx‘的解決辦法

我在轉換文件的時候遇到這個報錯&#xff0c;原因是文件名與已有文件名重復了 解決辦法很簡單&#xff0c;如下圖把" " 里的名字換成不重復的&#xff0c;再次允許代碼&#xff0c;會恢復正常

ue引擎游戲開發筆記(37)——實現敵人接收攻擊傷害,并作出反應

1.需求分析&#xff1a; 現在已經顯示造成實際傷害&#xff0c;但敵人對實際傷害并未產生反饋&#xff0c;例如還擊&#xff0c;或者死亡倒地等等&#xff0c;實現敵人對于受擊的反饋。 2.操作實現&#xff1a; 1.思路&#xff1a;在動畫藍圖中添加死亡動畫&#xff0c;并通過…

【姿態解算與濾波算法】

姿態解算 一、主線 姿態表示方式&#xff1a;矩陣表示&#xff0c;軸角表示&#xff0c;歐拉角表示&#xff0c;四元數表示。 慣性測量單元IMU&#xff08;Inertial Measurement Unit&#xff09;&#xff1a;MPU6050芯片&#xff0c;包含陀螺儀和加速度計&#xff0c;分別測…

winhex工具,將文件轉換為16進制數據放入代碼。

今天介紹winhex工具&#xff0c;可以將任何內容讀取讀取為16進制數據。下面看下效果。 下載鏈接&#xff1a; WinHex: Hex Editor & Disk Editor, Computer Forensics & Data Recovery Software 一、WinHex打開文件 我們要打開的文件&#xff1a; 打開后&#xff1a; 我…