隐式使用元类干预python中每个类的定义吗?

问题描述 投票:0回答:1

我一直在学习元类,我想知道是否有可能向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 global metaclass
1个回答
1
投票
  1. Python不允许修改内置的声明类型。那表示字典,列表,类在扩展中定义的类Numpy.ndarrays是从Python代码“冻结”的。

  2. 即使在可能的情况下,更改所有类的元类也不会更改已定义的类。因此,list等不会受到影响。不过,您可以安排程序,以便在导入具有类定义的任何其他模块之前可以“安装”您的类创建钩子-这样就可能影响以Python代码编写的类。 (在扩展中创建的类是用C代码定义的,无论如何都不会经历元类的创建过程)

  3. type被引用为对象的元类,因此即使您在内置函数中更改type-这是可能的,但不会自动用作任何人的元类。默认情况下使用它,因为它是type(object)返回的内容。

    话虽如此,可以在正在运行的Python程序中创建将通过所有existing

  4. 类进行搜索的东西,并且只要在Python中定义了该类,就可以修饰__getitem__方法(如果存在),接受关键字参数。

但是然后:

  1. PEP 472中提出的对带有索引参数的支持要求对解析器和语言规范进行更改-仅在__getitem__中接受关键字参数将不会使a[b=1]正常工作,或者不是语法错误。仍然需要写a.__getitem__(b=1)

  2. __getitem__中的索引名称对于一种对象非常特定。在没有考虑到这一点的情况下,对于any

    类设计是没有道理的。如果a是列表,则a[fish='golden']是什么意思?如果a是字典,该怎么办?
  3. 总而言之,如果您想出一些在索引中传递名称的意义,那么您已经有了一个很酷的类-然后您可以有任何方法来检索它,并使用该a.get(fish="gold")的常规括号符号,或者,甚至在编写__call__方法时也是如此:a(fish="gold")

© www.soinside.com 2019 - 2024. All rights reserved.