如何获取当前类对象的引用?

时间:2011-08-31 16:35:51

标签: python python-3.x pyqt

在Python中,如何在类语句中获取对当前类对象的引用?例如:

def setup_class_members(cls, prefix):
    setattr(cls, prefix+"_var1", "hello")
    setattr(cls, prefix+"_var2", "goodbye")

class myclass(object):
    setup_class_members(cls, "coffee")  # How to get "cls"?

    def mytest(self):
        print(self.coffee_var1)
        print(self.coffee_var2)

x = myclass()
x.mytest()

>>> hello
>>> goodbye


我已经注销的替代方案是:

  1. 使用locals():这会在可以写入的类语句中提供一个dict。这似乎适用于类,但文档告诉您不要这样做。 (如果有人可以向我保证这种情况会持续一段时间,我可能会选择这种替代方案。)

  2. class语句之后向类对象添加成员:我的实际应用程序是使用动态创建的QWidget类属性派生PyQt4 pyqtProperty类。 QWidget很不寻常,因为它有一个自定义元类。非常粗略地,元类编译pyqtProperties列表并将其存储为附加成员。因此,创建后添加到类中的属性不起作用。举例来说明这一点:

  3. from PyQt4 import QtCore, QtGui
    
    
    # works
    class MyWidget1(QtGui.QWidget):
        myproperty = QtCore.pyqtProperty(int)
    
    
    # doesn't work because QWidget's metaclass doesn't get to "compile" myproperty
    class MyWidget2(QtGui.QWidget):
        pass
    MyWidget2.myproperty = QtCore.pyqtProperty(int)
    

    请注意,上述内容适用于大多数编程案例;我的情况恰好是那些不寻常的角落案例之一。

4 个答案:

答案 0 :(得分:3)

AFAIK有两种方法可以做你想做的事:

  1. 使用metaclass,这将在类创建时创建两个变量(我认为这就是你想要的):

    class Meta(type):
        def __new__(mcs, name, bases, attr):
            prefix = attr.get("prefix")
            if prefix:
                attr[prefix+"_var1"] = "hello"
                attr[prefix+"_var2"] = "goodbye"
    
            return type.__new__(mcs, name, bases, attr)
    
    class myclass(object):
        __metaclass__ = Meta
        prefix = "coffee"
    
        def mytest(self):
            print(self.coffee_var1)
            print(self.coffee_var2)
    
  2. 在实例化时创建两个类变量:

    class myclass(object):      prefix =“coffee”

     def __init__(self):     
         setattr(self.__class__, self.prefix+"_var1", "hello")
         setattr(self.__class__, self.prefix+"_var2", "goodbye")
    
     def mytest(self):
         print(self.coffee_var1)
         print(self.coffee_var2)
    
  3. N.B:我不确定你想要实现什么,因为如果你想根据prefix变量创建动态变量,你为什么要像在mytest方法中一样进行访问?我希望这只是一个例子。

答案 1 :(得分:3)

对于Python 3,该类必须声明为

class myclass(object, metaclass = Meta):
   prefix = "coffee"
   ...


其他几点:

  • 元类可以是可调用的,而不仅仅是一个类(Python 2& 3)

  • 如果您班级的基类已经有非标准元类,则必须确保将其称为__init__()__new__()方法而不是类型。

    < / LI>
  • class语句接受传递给元类的关键字参数(仅限Python 3)

使用以上所有内容在Python 3中重写mouad的解决方案是......

def MetaFun(name, bases, attr, prefix=None):
    if prefix:
        attr[prefix+"_var1"] = "hello"
        attr[prefix+"_var2"] = "goodbye"

    return object.__class__(name, bases, attr)

class myclass(object, metaclass = MetaFun, prefix="coffee"):
    def mytest(self):
        print(self.coffee_var1)
        print(self.coffee_var2)

答案 2 :(得分:2)

您可以使用另外两种方法:

一个类装饰器。

def setup_class_members(prefix):

    def decorator(cls):
        setattr(cls, prefix+"_var1", "hello")
        setattr(cls, prefix+"_var2", "goodbye")
        return cls

    return decorator

@setup_class_members("coffee")
class myclass(object):
    # ... etc

特别是如果你需要以各种组合添加属性,装饰器方法很好,因为它对继承没有任何影响。

如果您要处理一组希望以各种方式组合的一小部分属性,则可以使用mixin类。 mixin类是一个常规类,它只是为了将各种属性“混合”到其他类中。

class coffee_mixin(object):
    coffee_var1 = "hello"
    coffee_var2 = "goodbye"

class tea_mixin(object):
    tea_var1 = "good morning old bean"
    tea_var2 = "pip pip cheerio"

class myclass(coffee_mixin, tea_mixin):
    # ... etc

答案 3 :(得分:1)

请参阅zope.interface.declarations._implements以获取此类魔法的示例。请注意,这是一个严重的可维护性和可移植性风险。