python超类
type就是Python在背后用来创建所有类的超类
str是用来创建字符串对象的类,而int是用来创建整数对象的类。type就是创建类对象的类。type就是创建类对象的类。你可以通过检查__class__属性来看到这一点。Python中所有的东西,注意,我是指所有的东西——都是对象。这包括整数、字符串、函数以及类。它们全部都是对象,而且它们都是从一个类创建而来。
>>> a = 6
>>> a.__class__
<class 'int'>
>>> b = 'string'
>>> b.__class__
<class 'str'>
# int和str的__class__是type
>>> a.__class__.__class__
<class 'type'>
>>> b.__class__.__class__
<class 'type'>
# type用来创建所有类的超类,没有比type更基础的类了
>>> a.__class__.__class__.__class__
<class 'type'>
python自定义超类
type就是Python的内建超类,当然了,你也可以创建自定义超类。
超类的主要目的就是为了当创建类时能够自动地改变类。
通过设定__metaclass__来实现,这个模块中的所有类都会通过这个超类来创建
使用函数创建自定义超类
def upper_attr(future_class_name, future_class_parents, future_class_attr):
'''返回一个类对象,将属性都转为大写形式'''
#选择所有不以'__'开头的属性
attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))
# 将它们转为大写形式
uppercase_attr = dict((name.upper(), value) for name, value in attrs)
#通过'type'来做类对象的创建
return type(future_class_name, future_class_parents, uppercase_attr)#返回一个类
class Foo(object):
__metaclass__ = upper_attr
bar = 'bip'
print(hasattr(Foo, 'bar'))
# 输出: False
print(hasattr(Foo, 'BAR'))
# 输出:True
f = Foo()
print(f.BAR)
# 输出:'bip'
例子输出(跑了下参考博客的这个例子,貌似没实现将属性转成大写,结果也与博客给出的输出相反,不过没关系,基本不用这种方法。)
root@ubuntu:/home/vickey/test# python t.py
True
False
Traceback (most recent call last):
File "t.py", line 131, in <module>
print(f.BAR)
AttributeError: 'Foo' object has no attribute 'BAR'
使用class自定义超类
如果我们希望能够控制对象的创建,可以通过改写
__new__实现
__new__是在__init__之前被调用的类方法,__new__是用来创建对象并返回对象的方法,而__init__只是用来将传入的参数初始化给对象,它是在对象创建之后执行的方法。
# v1
class UpperAttrMetaclass(type):
def __new__(upperattr_metaclass, future_class_name, future_class_parents, future_class_attr):
attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))
uppercase_attr = dict((name.upper(), value) for name, value in attrs)
# 复用type.__new__方法
# 这就是基本的OOP编程,没什么魔法。由于type是超类也就是类,因此它本身也是通过__new__方法生成其实例,只不过这个实例是一个类.
return type.__new__(upperattr_metaclass, future_class_name, future_class_parents, uppercase_attr)
# v2
class UpperAttrMetaclass(type):
def __new__(cls, name, bases, dct):
attrs = ((name, value) for name, value in dct.items() if not name.statswith('__'))
uppercase_attr = dict((name.upper(), value) for name, value in attrs)
return type.__new(cls, name, bases, uppercase_attr)
# v3
class UpperAttrMetaclass(type):
def __new__(cls, name, bases, dct):
attrs = ((name, value) for name, value in dct.items() if not name.startswith('__'))
uppercase_attr = dict((name.upper(), value) for name, value in attrs)
# 使用super方法的话,我们还可以使它变得更清晰一些
return super(UpperAttrMetaclass, cls).__new__(cls, name, bases, uppercase_attr)
github上的应用例子
class ProxyMetaclass(type):
def __new__(cls, name, bases, attrs):
count = 0
attrs['__CrawlFunc__'] = []
for k, v in attrs.item():
if 'crawl_' in k:
attrs['__CrawlFunc__'].append(k)
count += 1
attrs['__CrawlFuncCount__'] = count
return type.__new__(cls, name, bases, attrs)
# 调用自定义超类
class FreeProxyGetter(object, metaclass=ProxyMetaclass):
def get_raw_proxies(self, callback):
proxies = []
print('Callback', callback)
for proxy in eval("self.{}()".format(callback)):
print('Getting', proxy, 'from', callback)
proxies.append(proxy)
return proxies
在要创建的类中使用参数metaclass=YourMetaclass调用自定义的超类,这样就可以为所有调用了这个超类的类添加相同的属性了。例子会添加__CrawlFunc__和__CrawlFuncCount__两个属性用于表示爬虫函数,和爬虫函数个数