【问题标题】:Metaclass not altering attributes元类不改变属性
【发布时间】:2018-04-24 13:36:03
【问题描述】:

为什么以下元类没有将所有属性都转换为大写?相反,它似乎什么也没做。

class UpperAttrMetaclass(type):

    def __new__(cls, clsname, bases, dct):

        uppercase_attr = {}
        for name, val in dct.items():
            if not name.startswith('__'):
                uppercase_attr[name.upper()] = val
            else:
                uppercase_attr[name] = val

        return super(UpperAttrMetaclass, cls).__new__(cls, clsname, bases, uppercase_attr)


class MyKlass(object):
    __metaclass__ = UpperAttrMetaclass

    def __init__(self):
        print ("Instantiating the object in the __init__ of the class")

    def foo(self, param):
        pass

    some_attribute = 2

print("")
print ("--------------------------------------")
print ("This is the first line of the program")
print ("--------------------------------------")
m = MyKlass()
print(m)
print(m.__dict__)

【问题讨论】:

  • 您是否 100% 确定您使用的是 python 2 而不是 python 3?此外,您正在检查 instance 的字典,而不是 class 的字典。
  • 是的,这种语法在 python 3 中不起作用,并且肯定会调用元类。不管怎样。 MyKlass.__dict__ 或 m.__dict__ 具有较低的类属性
  • 你仍然在看错东西。试试print(MyKlass.__dict__)
  • 好吧,你是对的。所以只有类受到影响,而不是对象?
  • 是的,元类就是这样工作的。他们创建类,而不是实例。如果要更改实例属性,可以覆盖 __setattr__ 方法或将对象的 __dict__ 替换为自定义的类 dict 类,该类将其键转换为大写。

标签: python python-2.7 metaclass


【解决方案1】:

所以,从 cmets 来看,如果你想将所有实例属性直接设置为大写,你可以简单地在类本身上实现 __setattr__。 (也许__getattr__ 为了规范所有属性访问)

class UpperAttrMetaclass(type):

    def __new__(cls, clsname, bases, dct):

        uppercase_attr = {}
        for name, val in dct.items():
            if not name.startswith('__'):
                uppercase_attr[name.upper()] = val
            else:
                uppercase_attr[name] = val

        return super(UpperAttrMetaclass, cls).__new__(cls, clsname, bases, uppercase_attr)

   def __setattr__(cls, attr, value):
      if not attr.startswith("__"):
          attr  = attr.upper()
      super(UpperAttrMetaclass, cls).__setattr__(attr, value)

class MyKlass(object):
    __metaclass__ = UpperAttrMetaclass

    def __init__(self):
        print ("Instantiating the object in the __init__ of the class")

    def foo(self, param):
        pass

    def __setattr__(self, attr, value):
         super(MyKlass, self).__setattr_(attr.upper(), value)

    some_attribute = 2

同样使用元类上的__setattr__,您可以确保在创建类之后将类属性 et 也转换为大写。对于普通的实例属性,只需要类中的__setattr__即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-15
    • 2020-07-05
    • 1970-01-01
    • 2013-02-01
    • 2016-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多