一、动态添加属性
1. 给实例添加属性
class person:
def __init__(self, name):
self.name = name
p = person("alice")
# 动态添加属性
p.age = 25
p.city = "北京"
p.hobbies = ["阅读", "游泳"]
print(p.age) # 25
print(p.city) # 北京2. 给类添加属性
class person:
pass
# 给类动态添加属性
person.species = "human"
person.max_age = 120
p1 = person()
p2 = person()
print(p1.species) # human(所有实例共享)
print(p2.species) # human3. 使用setattr动态添加
class person:
pass
p = person()
setattr(p, "name", "alice")
setattr(p, "age", 25)
# 动态获取
print(getattr(p, "name")) # alice
print(getattr(p, "age")) # 25
print(getattr(p, "city", "未知")) # 未知(不存在时返回默认值)二、动态添加方法
1. 添加实例方法
实例方法的特点:第一个参数是 self,需要绑定到实例才能调用。
class person:
def __init__(self, name):
self.name = name
# 方式1:直接给类添加(所有实例可用)
def greet(self):
return f"hello, i'm {self.name}"
person.greet = greet
p = person("alice")
print(p.greet()) # hello, i'm alice
# 方式2:只给单个实例添加
import types
def say_hi(self):
return f"hi, {self.name}"
p2 = person("bob")
p2.say_hi = types.methodtype(say_hi, p2)
print(p2.say_hi()) # hi, bob
# p1.say_hi() # attributeerror,p1 没有这个方法2. 添加类方法
类方法的特点:第一个参数是 cls,用 @classmethod 装饰。
class person:
species = "human"
# 定义类方法
@classmethod
def get_species(cls):
return cls.species
@classmethod
def create_anonymous(cls):
return cls("匿名用户")
# 动态添加到类
person.get_species = get_species
person.create_anonymous = create_anonymous
# 调用
print(person.get_species()) # human
anonymous = person.create_anonymous()
print(anonymous.name) # 匿名用户
# 实例也可以调用
p = person("alice")
print(p.get_species()) # human也可以直接赋值(不需要 @classmethod 语法糖):
def get_species(cls):
return cls.species
person.get_species = classmethod(get_species)3. 添加静态方法
静态方法的特点:不需要 self 或 cls 参数,用 @staticmethod 装饰。
class person:
pass
# 定义静态方法
@staticmethod
def is_adult(age):
return age >= 18
@staticmethod
def format_name(first, last):
return f"{first} {last}"
# 动态添加到类
person.is_adult = is_adult
person.format_name = format_name
# 调用
print(person.is_adult(20)) # true
print(person.format_name("张", "三")) # 张 三
# 实例也可以调用
p = person()
print(p.is_adult(16)) # false同样可以不用装饰器语法:
person.is_adult = staticmethod(lambda age: age >= 18)
三、三种方法类型对比
| 类型 | 第一个参数 | 装饰器 | 调用方式 | 访问类属性 | 访问实例属性 |
|---|---|---|---|---|---|
| 实例方法 | self | 无 | obj.method() | 通过 self.__class__ | 通过 self |
| 类方法 | cls | @classmethod | class.method() 或 obj.method() | 直接 cls | 无 self |
| 静态方法 | 无 | @staticmethod | class.method() 或 obj.method() | 通过 cls | 无 self |
四、使用setattr添加方法
class calculator:
pass
# 定义各种方法
def add(self, x, y):
return x + y
@classmethod
def multiply(cls, x, y):
return x * y
@staticmethod
def subtract(x, y):
return x - y
# 使用 setattr 动态添加
setattr(calculator, "add", add)
setattr(calculator, "multiply", classmethod(multiply))
setattr(calculator, "subtract", staticmethod(subtract))
c = calculator()
print(c.add(3, 5)) # 8
print(calculator.multiply(3, 5)) # 15
print(calculator.subtract(10, 3)) # 7五、注意事项
1. 不能对__slots__类动态添加属性
class person:
__slots__ = ["name", "age"]
p = person()
p.name = "alice" # 允许
# p.city = "北京" # attributeerror2. 动态添加的方法不会出现在类定义中
# 使用 inspect 查看
import inspect
class person:
pass
def greet(self):
return "hello"
person.greet = greet
print("greet" in dir(person)) # true
print(inspect.ismethod(person.greet)) # false(是函数,还未绑定)3. 可以统一用setattr管理动态添加
def add_method(cls, name, func, method_type="instance"):
if method_type == "class":
setattr(cls, name, classmethod(func))
elif method_type == "static":
setattr(cls, name, staticmethod(func))
else:
setattr(cls, name, func)
# 使用
def say_hello(self):
return "hello"
add_method(person, "say_hello", say_hello, "instance") 其实动态添加方法的关键是:实例方法直接赋值,类方法用 classmethod() 包装,静态方法用 staticmethod() 包装。给类添加则所有实例可用,给单个实例添加需要用 types.methodtype 绑定。
以上就是python动态添加属性和方法的技巧的详细内容,更多关于python动态添加属性和方法的资料请关注代码网其它相关文章!
发表评论