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

发布于 2024-12-02 05:40:23 字数 1140 浏览 3 评论 0原文

在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():这在类语句中提供了一个可以写入的字典。这似乎适用于类,但文档告诉您不要这样做。 (如果有人可以向我保证这将继续工作一段时间,我可能会倾向于使用这种替代方案。)

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

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)

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

In Python, how do I get a reference to the current class object within a class statement? Example:

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

Alternatives that I've written off are:

  1. Use locals(): This gives a dict in a class statement that can be written to. This seems to work for classes, however the documentation tells you not to do this. (I might be tempted to go with this alternative if someone can assure me that this will continue to work for some time.)

  2. Add members to the class object after the class statement: My actual application is to derive a PyQt4 QWidget class with dynamically created pyqtProperty class attributes. QWidget is unusual in that it has a custom metaclass. Very roughly, the metaclass compiles a list of pyqtProperties and stores it as additional member. For this reason, properties that are added to the class after creation have no effect. An example to clear this up:

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)

Please note that the above will work for most programming cases; my case just happens to be one of those unusual corner cases.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

我是男神闪亮亮 2024-12-09 05:40:23

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

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

其他几点:

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

  • 如果您的类的基类已经有一个非标准元类,您必须确保调用它的 __init__()__new__() 方法而不是类型的方法。

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

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

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)

For Python 3, the class must be declared as

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

A few other points:

  • The metaclass may be a callable, not just a class (Python 2&3)

  • If the base class of your class already has a non-standard metaclass, you have to make sure you call it's __init__() and __new__() methods instead of type's.

  • The class statement accepts keyword parameters that are passed on to the metaclass (Python 3 only)

A rewrite of mouad's solution in Python 3 using all of the above is...

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)
罗罗贝儿 2024-12-09 05:40:23

据我所知,有两种方法可以完成您想要的操作:

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

    类元(类型):
        def __new__(mcs、名称、基础、属性):
            前缀 = attr.get("前缀")
            如果前缀:
                attr[前缀+"_var1"] = "你好"
                attr[前缀+"_var2"] = "再见"
    
            返回类型.__new__(mcs, 名称, 基础, 属性)
    
    类 myclass(对象):
        __元类__ = 元
        前缀=“咖啡”
    
        def mytest(自我):
            打印(self.coffee_var1)
            打印(self.coffee_var2)
    

  2. 在实例化时创建两个类变量:

    类 myclass(对象):
    前缀=“咖啡”

     def __init__(self):     
         setattr(self.__class__, self.prefix+"_var1", "你好")
         setattr(self.__class__, self.prefix+"_var2", "再见")
    
     def mytest(自我):
         打印(self.coffee_var1)
         打印(self.coffee_var2)
    

注意:我不确定你想要实现什么,因为如果你想根据 prefix 变量创建动态变量,为什么你要像在 mytest 中那样访问方法?!我希望这只是一个例子。

AFAIK there is two way to do what you want:

  1. Using metaclass, this will create your two variables in class creation time (which i think is what you want):

    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. Create your two class variable in instantiation time:

    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)
    

N.B: I'm not sure what you want to achieve because if you want to create dynamic variables depending on the prefix variable why are you accessing like you do in your mytest method ?! i hope it was just an example.

_畞蕅 2024-12-09 05:40:23

您还可以使用两种方法:

类装饰器。

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

Two more approaches you might use:

A class decorator.

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

Especially if you need to add attributes in various combinations, the decorator approach is nice because it does not have any effect on inheritance.

If you are dealing with a small set of of attributes that you wish to combine in various ways, you can use mixin classes. A mixin class is a regular class, it's just intended to "mix in" various attributes to some other class.

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
誰認得朕 2024-12-09 05:40:23

请参阅 zope.interface.declarations ._implements 作为实现这种魔法的示例。请注意,这是一个严重的可维护性和可移植性风险。

See zope.interface.declarations._implements for an example of doing this kind of magic. Just be warned that it's a serious maintainability and portability risk.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文