Python是动态语言,动态类型语言,也是强类型语言。所以Python可以在运行时改变自身结构,动态添加/删除属性和方法。接下来将介绍Python如何动态添加属性和方法。
class Person(object):
def __init__(self, newName, newAge):
self.name = newName
self.age = newAge
zhangsan = Person("张三", 18)
zhangsan.addr = "北京" # 类对象zhangsan动态添加对象属性addr
print(zhangsan.name) # 张三
print(zhangsan.age) # 18
print(zhangsan.addr) # 北京
lisi = Person("李四", 28)
print(lisi.name) # 李四
print(lisi.age) # 28
print(lisi.addr) # 'Person' object has no attribute 'addr'
由以上代码可知,Person类有两个属性:name和age。通过[对象名.属性名]给类对象zhangsan动态添加了对象属性addr,而Person的另一个类对象lisi却不能调用这个属性。
注:通过对象名添加的对象属性,只有这个对象能使用
class Person(object):
def __init__(self, newName, newAge):
self.name = newName
self.age = newAge
Person.addr = "北京" # 类Person动态添加类属性addr
zhangsan = Person("张三", 18)
print(zhangsan.name) # 张三
print(zhangsan.age) # 18
print(zhangsan.addr) # 北京
lisi = Person("李四", 28)
print(lisi.name) # 李四
print(lisi.age) # 28
print(lisi.addr) # 北京
由以上代码可知,通过[类名.属性名]给类Person动态添加了类属性addr,Person的类对象zhangsan和lisi都能调用这个属性
注:通过类名添加的类属性,这个类的所有对象都能使用
类中有三种方法,实例方法,静态方法和类方法,三种方法的区别如下:
import types
class Person(object):
def __init__(self, newName, newAge):
self.name = newName
self.age = newAge
def eat(self):
print("---正在吃---")
def run(self):
print("---正在跑---")
zhangsan = Person("张三", 18)
zhangsan.eat() # ---正在吃---
zhangsan.run = types.MethodType(run, zhangsan) # 类对象zhangsan动态添加对象方法run()
zhangsan.run() # ---正在跑---
lisi = Person("李四", 28)
lisi.eat() # ---正在吃---
lisi.run() # 'Person' object has no attribute 'run'
由以上代码可知,Person类有一个方法:eat()方法。通过[types.MethodType(方法名, 对象名)]给类对象zhangsan动态添加了对象方法run(),同理,Person的另一个类对象lisi不能调用这个方法
注:通过对象名添加的对象方法,只有这个对象能使用
class Person(object):
def __init__(self, newName, newAge):
self.name = newName
self.age = newAge
def eat(self):
print("---正在吃---")
@staticmethod
def staticRun():
print("---正在跑---")
Person.staticRun = staticRun # 类Person动态添加静态方法staticRun()
Person.staticRun() # ---正在跑---
zhangsan = Person("张三", 18)
zhangsan.eat() # ---正在吃---
zhangsan.staticRun() # ---正在跑---
lisi = Person("李四", 28)
lisi.eat() # ---正在吃---
lisi.staticRun() # ---正在跑---
由以上代码可知,通过[类名.静态方法名]给类Person动态添加了静态方法staticRun(),Person类的Person的类对象zhangsan和lisi都能调用这个方法
注:通过类名添加的静态方法,这个类及这个类的所有对象都能使用
class Person(object):
def __init__(self, newName, newAge):
self.name = newName
self.age = newAge
def eat(self):
print("---正在吃---")
@classmethod
def classRun(cls):
print("---正在跑---")
Person.classRun = classRun # 类Person动态添加类方法classRun()
Person.classRun() # ---正在跑---
zhangsan = Person("张三", 18)
zhangsan.eat() # ---正在吃---
zhangsan.classRun() # ---正在跑---
lisi = Person("李四", 28)
lisi.eat() # ---正在吃---
lisi.classRun() # ---正在跑---
由以上代码可知,通过[类名.类方法名]给类Person动态添加了类方法classRun(),Person类的Person的类对象zhangsan和lisi都能调用这个方法
注:通过类名添加的类方法,这个类及这个类的所有对象都能使用
通过以上内容,我们知道了如何动态的添加属性和方法。但是,如果我们想要限制class的属性该怎么办?例如:只允许Person实例添加name和age属性。为了达到这个目的,Python允许在定义class的时候,定义一个特殊变量__slots__来限制该class能添加的属性。
import types
class Person(object):
__slots__ = ("name", "age") # 定义__slots__
def __init__(self, newName, newAge):
self.name = newName
self.age = newAge
def eat(self):
print("---正在吃---")
def run(self):
print("---正在跑---")
Person.num = 100 # 类Person动态添加类属性num
zhangsan = Person("张三", 18)
print(zhangsan.name) # 张三
print(zhangsan.age) # 18
print(zhangsan.num) # 100
zhangsan.eat() # ---正在吃---
zhangsan.addr = "北京" # 'Person' object has no attribute 'addr'
zhangsan.run = types.MethodType(run, zhangsan) # 'Person' object has no attribute 'run'
通过以上代码可知,__slots__对Person类的动态添加没有限制,而Person类对象zhangsan不能再动态添加对象属性和方法。
对于__slot__有以下几个需要注意的地方: