Python-元类编程

元类编程之前先学习两个魔法函数

#  __getattr__ 和__getattribute__魔法函数
#  __getattr__  查找不到属性的时候调用
#  __getattribute__

from datetime import date

class User:
    def __init__(self, name, birthday,info={}):
        self.name = name
        self.birthday = birthday
        self.info = info

    # 在查找不到属性的时候调用
    def __getattr__(self, item):
        # print('attribute not find')
        # print(item)
        # return 'attribute not find'
         return self.info[item]
        #  return self.info.get(item)

    # __getattribute__在__getattr__之前执行 不轻易去重写
    # def __getattribute__(self, item):
    #     return 'juran'


# 打印没有反回值的函数返回None
# def demo(): pass
# print(demo())     # None


if __name__ == '__main__':
    # 1990-1-1
    user = User('ellen', date(year=1990, month=1, day=1),info={'age':18})
    # print(user.name)  
    print(user.age)    # 18
    #print(user.birthday)

属性描述符

class User(object):
    def __init__(self, age):
        self.age = age

    def get_age(self):
        return self.age

    def set_age(self,age):
        if not isinstance(age,int):
            raise TypeError('Type Error')
        self.age = age
        
# 以上只是对age一个属性做整数验证,如果还有姓名name属性等,也要做字符串验证,   
# 比较麻烦,可以用什么方法解决?就可用属性描述符:
# 属性描述符 __get__ __set__ __delete__
# Django

class IntFild(object):
    '''数据描述符 有__get__ 和__set__等方法 只有 __get__是非数据描述符'''
    def __get__(self, instance, owner):
        print('__get__')
        print(owner)
        print(instance)     
        return self.values    # 

    def __set__(self, instance, value):
        print('__set__')
        print(instance)      # 对象
        # print(value)		# 值 30 对值做验证
        if not isinstance(value,int):
            raise ValueError('Value Error')
        self.values = value


    def __delete__(self, instance):
        pass

# 非数据属性描述 只有  __get__ 方法
class NoneDataIntFild:
    def __get__(self, instance, owner):
        return owner

class User:
    age = IntFild()

user = User()
user.__dict__['age'] = 18
user.age = 30
print(user.age)

属性查找顺序
user = User 那么user.age 顺序如下

  1. 如果’age’是出现在User或其基类的__dict__中 且age是data descriptor
    那么调用其__get__方法,否则 5-抛出AttributeError
    2.如果’age’是出现在User的__dict__中 那么返回obj.dict[‘age’],否则 5
    3.如果’age’是出现在User或其基类的__dict__中,两各种情况:
    3.1 如果age是non-data descriptor,那么调用其__get__方法 否则5
    3.2 返回__dict__[‘age’]
  2. 如果User有__getattr__方法 调用__getatter方法
    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)        # user
     # print(type(obj))

元类就是创建类的类 就是说的type
动态创建类

使用type创建类


'''
type两个功能:
1.可以用type查看数据类型
2.还可以动态的创建类 type(类名:由父类组成的元组,包含属性的字典)

metacalss 属性
如果一个类中定义了metacalss = xxx.Python就会用元类的方式来创建类
'''

'''
type(name, bases, dict) -> a new type   
name - > 类名
bases -> 继承
dict -> 方法
'''
# 使用type创建类和一般正常创建的类一样没有区别

User = type('User',(),{})
obj = User()
print(obj)      # 相当于创建了类 <__main__.User object at 0x00000000021A8630>

# 添加属性
User = type('User',(),{'name':'ellen'})
obj = User()
print(obj)
print(obj.name)     # ellen

# 添加一个方法
def demo(self):
    return self.name


def get_age(self):
     self.age = 18
     return self.age

# 定义魔法方法 尽量不用魔法方法创建方法
def  __init__(self):
    self.sex = 1


User = type('User',(),{'name':'ellen','info': demo,'age': get_age,})
obj = User()
print(obj.info())
print(obj.age())


# 类的继承
class BaseClass(object):
    def test(self):
        return 'base class'

    # 可以继承魔法方法
    def __str__(self):
        return 'this is test'


class BaseClass1(BaseClass):
    def test1(self):
        return 'base class1'

b = BaseClass()
print(b)     #  this is test


User = type('User',(BaseClass,BaseClass1),{'name':'ellen'})
user = User()
print(user.test())   # 继承 base class
print(user.test1())   #  可继承多个 base class1



# 正常创建类
class User1(object):
    pass

obj1 = User()
print(obj1)      # <__main__.User object at 0x00000000021A8748>

metaclass 属性

# metaclass 属性 python2 和 pytho3 有区别
'''
如果一个类中定义了metaclass = xxx.Python就会用元类方式创建类
从而可以控制类的创建行为

'''

'''
def upper_attr(class_name,class_parent,class_attr):  # 1.传类名 2.继承父类,3.类的属性
    # print(class_name)
    # print(class_parent)
    # print(class_attr)
    newattr = {}
    for name,value in class_attr.items():
        # print(name)
        # print(value)
        if not name.startswith('_'):
            newattr[name.upper()] = value

    return type(class_name,class_parent,newattr)

class Foo(object,metaclass=upper_attr):
    name = 'ellen'


f = Foo()
print(hasattr(Foo,'name'))
print(hasattr(Foo,'Name'))

# print(f.NAME)
# print(f.Name)

'''

# 类的实例化中 首先寻找metaclass 如果没有再找其他类
class Demo(object):
    def __new__(cls, *args, **kwargs):
        pass

class MetaClass(type):
    def __new__(cls, *args, **kwargs):
        pass

class User(Demo,metaclass= MetaClass):
    pass


obj = User()
发布了106 篇原创文章 · 获赞 0 · 访问量 2386

猜你喜欢

转载自blog.csdn.net/weixin_45905671/article/details/105282263
今日推荐