装饰器给函数加功能,元类可以给类加功能。
type(class_name, class_parents, class_attr)
# 其中class_name类型为字符串,class_parents为元组,class_attr为字典类型,字典的key用字符串表示class熟悉名。
将类中不是__开头的属性名字变为大写
def upper_attr(class_name, class_parent, class_attr): # 该函数返回一个由type()创建的类
# 遍历属性字典,把不是__开头的属性名变为大写
new_attr = {}
for key, name in class_attr.items():
if not name.startwith("__"):
new_attr[name.upper()] = value
# 调用type来创建一个类
return Foo(object, class_parents, new_attr)
class Foo(object, metaclass=upper_attr): # metaclass = ...表示不使用默认的type()来创建类,而是使用自定义的函数upper_attr()来创建类。
print(hasattr(Foo, 'bar'))
print(hasattr(Foo, 'BAR'))
方法二:
class UpperAttrMetaClass(type): # 继承了type就为元类
# __new__ 是在__init__之前被调用的特殊方法
# __new__ 是用来创建对象并返回之的方法
# 而__init__只是将传入的参数初始化给对象
# 很少需要用到__new__,除非希望能够控制对象的创建
# 这里,创建的对象是类,我们希望能够自定义它,所以我们这里改写了__new__
# 当然,也可以在__init__中做些事情
# 还有一些高级的用法会涉及到改写__call__特殊方法,但我们这里不用
def __new__(cls, class_name, class_parents, class_attr): # cls表__new__为类属性
# 遍历属性字典,把不是__开头的属性名字变为大写
new_attr = {}
for name, value in class_attr.items():
if not name.startswith("__"):
new_attr[name.upper()] = value
# 方法1:通过‘type’来做类对象的创建
return type(class_name, class_parents, new_attr) #__new__方法必须有返回值,且该返回值为对象。
# 方法2:复用type.__new__方法
# 这是基本的OOP编程,没有什么魔法
# return type.__new__(cls, class_name, class_parents, new_attr)
__new__与__init__中self的关系:__new__创建并返回了实例对象self,该self作为了__init__的第一个参数。
参考资料
浅谈python中的实例方法self、类方法cls和静态方法
python类的实例方法、静态方法和类方法区别及其应用场景
面向对象中__new__和__init__的区别