我一直在学习元类,我想知道是否有可能向python中定义的每个类添加一个新属性,而不仅是那些从自定义元类显式继承的类。
我可以使用这样的自定义元类显式添加新属性
class NewAttrMeta(type):
def __new__(cls, name, bases, attrs):
attrs['new_attr'] = 'new_thing'
return super().__new__(cls, name, bases, attrs)
class A(metaclass=NewAttrMeta):
...
print(A.new_attr)
$ 'new_thing'
但是是否可以对定义的every类进行这样的更改,而不仅仅是在自定义元类中显式继承的类?
[我想可能所有类都是type
类型,如果我用自定义元类重写type
本身,那么所有新类都可能继承自它。并且由于元类是type
的子类,因此以这种方式定义的所有类将仍然有效...
class NewAttrMeta(type):
def __new__(cls, name, bases, attrs):
attrs['new_attr'] = 'new_thing'
return super().__new__(cls, name, bases, attrs)
type = NewMagicMeta
但是这仅在再次显式传递type
时有效:
class A(type):
...
print(A.new_attr)
$ 'new_thing'
class B():
...
print(B.new_attr)
$ AttributeError: type object 'A' has no attribute 'new_attr'
为什么我要这样做?我想看看我是否可以通过覆盖定义了PEP 472: "Support for indexing with keyword arguments"任何版本的每个类的__getitem__
方法来本地实现被拒绝的__getitem__
版本。我这样做只是为了好玩,所以我会对执行此操作的任何见解或其他方式感兴趣(黑客越多越好!)。
Python不允许修改内置的声明类型。那表示字典,列表,类在扩展中定义的类Numpy.ndarrays是从Python代码“冻结”的。
即使在可能的情况下,更改所有类的元类也不会更改已定义的类。因此,list
等不会受到影响。不过,您可以安排程序,以便在导入具有类定义的任何其他模块之前可以“安装”您的类创建钩子-这样就可能影响以Python代码编写的类。 (在扩展中创建的类是用C代码定义的,无论如何都不会经历元类的创建过程)
type
被引用为对象的元类,因此即使您在内置函数中更改type
-这是可能的,但不会自动用作任何人的元类。默认情况下使用它,因为它是type(object)
返回的内容。
话虽如此,可以在正在运行的Python程序中创建将通过所有existing
__getitem__
方法(如果存在),接受关键字参数。但是然后:
PEP 472中提出的对带有索引参数的支持要求对解析器和语言规范进行更改-仅在__getitem__
中接受关键字参数将不会使a[b=1]
正常工作,或者不是语法错误。仍然需要写a.__getitem__(b=1)
__getitem__
中的索引名称对于一种对象非常特定。在没有考虑到这一点的情况下,对于any
a
是列表,则a[fish='golden']
是什么意思?如果a
是字典,该怎么办? 总而言之,如果您想出一些在索引中传递名称的意义,那么您已经有了一个很酷的类-然后您可以有任何方法来检索它,并使用该a.get(fish="gold")
的常规括号符号,或者,甚至在编写__call__
方法时也是如此:a(fish="gold")