萌新学 Python 之动态绑定属性和方法以及魔法函数
动态修改属性和方法是指在定义类时没有添加,在执行过程中添加属性和方法,不改变原来的类结构
动态修改类属性:类名.类属性 = 属性值
当类属性存在时,修改属性值;当类属性不存在时,添加类属性,即动态绑定新的类属性
动态修改实例属性:对象.实例属性 = 属性值
当实例属性存在时,修改实例属性值,当实例属性不存在时,添加实例属性,即动态绑定新的实例属性
动态修改实例方法绑定到对象:对象.实例方法 = 实例方法
实例方法就是函数,在添加方法时,方法名后面不用加小括号,否则是函数调用
动态绑定实例方法到类:类名.实例方法 = 新实例方法
动态绑定类方法到类:类名.方法名 = classmethod(类方法)
类和对象的内置属性:__name__ 内置属性,返回类名、__dict__ 内置属性,以字典形式返回类的属性和方法
上述举例如下:
# 设计银行账号的存取款功能
# 创建类,有类属性,类方法,实例属性,实例方法
class Bankaccount:
bank_name = '中国银行'
bank_address = '北京'
def __init__(self, username, bank_card = '123456', band_pwd = '888888', balance = 100):
self.username = username
self.bank_card = bank_card
self.bank_pwd = band_pwd
self.balance = balance
# 存款功能
def deposit(self, amount):
if amount >= 100:
self.balance += amount
return self.balance
else:
return '存款不低于100元'
# 取款功能
def withdraw(self, amount):
if amount > self.balance:
return '余额不足'
else:
self.balance -= amount
return self.balance
# 类方法
@classmethod
def check_balance(cls, instance):
return instance.balance
# 实例化对象
bank1 = Bankaccount('张三')
bank1.deposit(200)
print(bank1.balance) # 300
# 动态修改类属性:类名.类属性 = 属性值
Bankaccount.bank_address = '上海' # 修改地址从北京更换为上海
print(bank1.bank_address) # 上海
# 动态绑定新的类属性
Bankaccount.phone = '123456789' # phone 是没有的类属性
# 类调用
print(Bankaccount.phone) # 123456789
# 实例对象调用
print(bank1.phone) # 123456789
# 动态修改实例属性:对象.实例属性 = 属性值
bank1.bank_pwd = '333333' # 修改密码从888888更换为333333
print(bank1.bank_pwd) # 333333
# 动态添加实例属性
bank1.sex = '男' # sex 是没有的实例属性
print(bank1.sex) # 男
# 动态修改实例方法,绑定到对象:对象.实例方法 = 实例方法
def deposit(amount):
if amount > 0:
bank1.balance += amount
return bank1.balance
else:
return '存款金额要大于0'
# 绑定 deposit 函数到对象 bank1
bank1.deposit = deposit
# 初始设置的存款金额必须大于100才能存入,修改成大于0后,用动态修改的实例方法在低于100时也能存入
print(bank1.deposit(10)) # 310
# 动态绑定方法到类(所有对象都有的方法):类名.实例方法 = 新实例方法
def affluent(instance):
result = Bankaccount.check_balance(instance)
name = instance.username
return f'{name}富裕' if result > 100 else f'{name}贫穷'
# 将 affluent 函数绑定到类中,即实例方法
Bankaccount.affluent = affluent
print(Bankaccount.affluent(bank1)) # 张三富裕
# 动态绑定类方法到类:类名.方法名 = classmethod(类方法)
def new_cls_method(cls):
return '类方法'
Bankaccount.cls_method = classmethod(new_cls_method)
print(Bankaccount.cls_method()) # 类方法
# 类和对象的内置属性
# __name__ 内置属性,返回类名
print(Bankaccount.__name__) # Bankaccount
# __dict__ 内置属性,以字典形式返回类的属性和方法
print(Bankaccount.__dict__)
魔法函数:首尾双下划线,比如 __init__ 等
__init__:构造函数,主要用来初始化实例属性
__call__:使自定义对象兼容函数的功能,可以把对象当作函数进行调用
__len__:使对象兼容 len 内置函数,获取对象的长度
__getitem__:使对象兼容列表、字典的索引和键的操作,把对象当作列表和字典使用,列表还可以进行切片,__getitem__ 当作列表、字典只能进行访问
__setitem__:使对象兼容列表、字典的索引和键的操作,把对象当作列表和字典使用,列表还可以进行切片,__setitem__ 当作列表、字典可以进行修改
__delitem__:使对象兼容列表、字典的索引和键的操作,把对象当作列表和字典使用,列表还可以进行切片,__delitem__ 当作列表、字典可以进行删除
__str__:对类进行说明
__iter__:迭代器,与 __next__ 一起使用,通过迭代器获取值,返回集合,元素去重且无序
# 创建类
class Magic:
# __init__ 构造函数,主要用来初始化实例属性
def __init__(self, items, index = 0):
self.items = items
self.index = index
# __call__ 使自定义对象兼容函数的功能,可以把对象当作函数进行调用
def __call__(self, *args, **kwargs): # *args 位置参数,**kwargs 关键字参数
return [_/self.items for _ in args]
# __len__ 使对象兼容 len 内置函数,获取对象的长度
def __len__(self):
return len(self.items)
# __getitem__ 使对象兼容列表、字典的索引和键的操作,把对象当作列表和字典使用,列表还可以进行切片
# __getitem__ 当作列表、字典只能进行访问
def __getitem__(self, item):
if isinstance(item, slice): # slice 切片
return self.items[item.start : item.stop : item.step]
return self.items[item]
# __setitem__ 使对象兼容列表、字典的索引和键的操作,把对象当作列表和字典使用,列表还可以进行切片
# __setitem__ 当作列表、字典可以进行修改
def __setitem__(self, key, value):
if isinstance(key, slice):
self.items[key.start : key.stop : key.step] = value
self.items[key] = value
# __delitem__ 使对象兼容列表、字典的索引和键的操作,把对象当作列表和字典使用,列表还可以进行切片
# __delitem__ 当作列表、字典可以进行删除
def __delitem__(self, key):
if isinstance(key, slice):
del self.items[key.start : key.stop : key.stop]
else:
del self.items[key]
# __str__ 对类进行说明
def __str__(self):
return '魔法函数'
# __iter__ 迭代器,与 __next__ 一起使用
def __iter__(self):
return self
def __next__(self):
if self.index < len(self.items):
result = self.items[self.index]
self.index += 1
return result
else:
raise StopIteration # 抛出异常
'上述魔法函数的应用如下:'
# __call__ 内置函数
my_instance1 = Magic(10)
print(my_instance1(1, 2)) # [0.1, 0.2]
# __len__ 获取对象的长度
my_instance2 = Magic('Hello')
print(len(my_instance2)) # 5
# __getitem__ 把对象当作列表进行访问
my_instance3 = Magic(['a', 1, 'b', 2])
print(my_instance3[2]) # b
print(my_instance3[::2]) # ['a', 'b']
# __setitem__ 把对象当作列表进行修改
my_instance4 = Magic(['a', 1, 'b', 2])
my_instance4[3] = 'c'
print(my_instance4.items) # ['a', 1, 'b', 'c']
# __delitem__ 把对象当作列表进行删除
my_instance5 = Magic(['a', 1, 'b', 2])
del my_instance5[0] # del 可以索引也可以切片
print(my_instance5.items) # [1, 'b', 2]
# __str__ 对类进行说明
print(my_instance1) # 魔法函数
# __iter__ 对象当作迭代器使用
my_instance6 = Magic(('a', 'a', 'b', 'b'))
# 通过迭代器获取值,返回集合,元素去重且无序
print({i for i in my_instance6}) # {'b', 'a'}