getattr和getattribute魔法函数
from datetime import date,datetime
class User:
def __init__(self,name,birthday):
self.name = name
self.birthday = birthday
def __getattr__(self,item):
print("not find attr")
def __getattribute__(self,item):
return "juran"
if __name__ == "__main__":
user = User("juran",date(year=1990,month=1,day=1))
print(user.age)
属性描述符
class User:
def __init__(self,age):
self.age = age
def get_age(self):
return (str(self.age) + '岁')
def set_age(self,age):
if not isinstance(age,int):
raise TypeError('Type Error')
self.age = age
如果User类中有多个属性都需要判断,那么就需要写多个方法,这些方法怎么复用呢?这个时候就要用到属性描述符
属性描述符,只要实现了get,set,delete任何一个方法,就被称为属性描述符
属性查找顺序
user = User(), 那么user.age 顺序如下:
1 如果"age"是出现在User或其基类的dict中, 且age是data descriptor,那么调用其get方法, 否则
2 如果"age"出现在user的dict中, 那么直接返回 obj.dict['age'],否则
3 如果"age"出现在User或其基类的dict中
3.1 如果age是non-data descriptor,那么调用其get方法, 否则
返回 dict['age']
4 如果User有getattr方法,调用getattr方法,否则
5 抛出AttributeError
自定义元类
动态创建类
def create_class(name):
if name == "user":
class User:
def __str__(self):
return "user"
return User
elif name == "student":
class Student:
def __str__(self):
return "Student"
return Student
if __name__ == "__main__":
myclass = create_class('user')
obj = myclass()
print(obj)
print(type(obj))
使用type创建类
type还可以动态的创建类,type(类名,由父类组成的元组,包含属性的字典)
- 第一个参数:name表示类名称,字符串类型
- 第二个参数:bases表示继承对象(父类),元组类型,单元素使用逗号
- 第三个参数:dict表示属性,这里可以填写类属性、类方式、静态方法,采用字典格式,key为属性名,value为属性值
- 建议魔法方法不用type()里面的dict来创建
'''
type(name, bases, dict) -> a new type
'''
def demo(self):
return self.name
def get_age(self):
self.age = 18
return self.age
User = type("User", (), {'name': '张老三', "info": demo, "age": get_age})
# dict 中name是对User类中添加属性
# dict 中info是对User类中添加demo方法
# dict 中age是对User类中添加get_age方法
obj = User()
print(obj.name) >>>张老三
print(obj.info()) >>> 张老三
print(obj.age()) >>> 18
# 多重继承
class BaseClass(object):
def test(self):
return "base class"
def __str__(self):
return "this is test"
class BaseClass1(object):
def test1(self):
return "base class1"
User = type("User", (BaseClass, BaseClass1), {'name': 'juran'})
user = User()
print(user)
>>> this is test
print(user.test1())
>>> base class1
总结:
元类:创建类的类
元类:type(name, bases, dict)
解释:type(类名,由父类组成的元组,包含属性的字典)
- 第一个参数:name表示类名称,字符串类型
- 第二个参数:bases表示继承对象(父类),元组类型,单元素使用逗号
- 第三个参数:dict表示属性,这里可以填写类属性、类方式、静态方法,采用字典格式,key为属性名,value为属性值
metaclass属性
如果一个类中定义了metalass = xxx,Python就会用元类的方式来创建类,metalass的优先级大于继承的父类,可参考实例,如下:
def upper_attr(class_name, class_parents, class_attr):
newattr = {}
for name, value in class_attr.items():
if not name.startswith("_"):
newattr[name.upper()] = value
return type(class_name, class_parents, newattr)
class Foo(object, metaclass=upper_attr):
# __metaclass__ = upper_attr
name = 'juran'
f = Foo()
# print(hasattr(Foo, 'name'))
# print(hasattr(Foo, 'NAME'))
print(f.NAME)
>>>juran
print(f.name)
>>> AttributeError: 'Foo' object has no attribute 'name'