python 如何在方法中同时访问cls和self

l2osamch  于 2023-04-28  发布在  Python
关注(0)|答案(3)|浏览(134)

我希望有代码可以做这样的事情

class myClass:

    def __init__(self):
        self.__var1 = 'var1'
    
    var2 = 'var2'

    def myNormalMethod(self):
        print(self.__var1)

    @classmethod
    def myClassMethod(cls):
       print(cls.__var2)
    
    #How do I do this?
    def myMethod():
        print(self.__var1)
        print(cls.__var2)

现在,最后一个方法不起作用,因为我不知道如何才能同时访问selfcls。我该如何实现这一点?

ssm49v7z

ssm49v7z1#

作为一个非常简单的回顾,self引用的是类的当前示例,而cls变量附加到类itelf i。即在每个示例之间共享。这里有一些参考资料来帮助解决这个问题,以及我是如何得到你的解决方案的:

我修改了您的示例代码以说明差异,并包含了一个解决方案:

class MyClass:
    __var2 = 'var2'
    var3 = 'var3'

    def __init__(self):
        self.__var1 = 'var1'

    def normal_method(self):
        print(self.__var1)

    @classmethod
    def class_method(cls):
       print(cls.__var2)

    def my_method(self):
        print(self.__var1)
        print(self.__var2)
        print(self.__class__.__var2)

if __name__ == '__main__':
    print(MyClass.__dict__['var3'])

    clzz = MyClass()
    clzz.my_method()

__var2var3是保存到类中的变量。您可以通过__dict__访问任何类变量,而无需示例。
由于类变量成为每个示例的一部分,因此只需调用self即可访问它们。或者,您可以显式调用self.__class__.__var2来明确预期变量的实际存储位置。

btqmn9zl

btqmn9zl2#

您可以只执行self.__var2-在示例上未找到的任何属性都将在类中自动查找。
要明确表示您希望属性来自类本身,请使用self.__class__.__var2

iezvtpos

iezvtpos3#

TL;DR:您可以使用描述符来实现这一点。
虽然现有的答案适用于OP的情况,但它们通常不能解决“如何在方法中同时访问cls和self”。
例如,下面是两个Python类的定义:

class MyClass:

    def __init__(self, name):
        self.name = name

    # TODO: def foo

class MySubclass(MyClass):
    pass

我想实现MyClass.foo,使其对MyClass的任何子类MySubclass表现出以下行为:

MySubclass.foo() == MySubclass.__name__
MySubclass(name="bar").foo() == "bar"

如果可以在方法中同时传递clsself,这将很容易:

# Does not work because `self` is never set
@classmethod
def foo(cls, self=None):
    if self:
        return self.name
    return cls.__name__

在这种情况下,你可以使用描述符来构建一个对象,它模仿你希望你的方法具有的行为:

class MyDescriptor:

    def __get__(self, instance, cls):  # instance = self, cls = cls
        if instance is None:
            return lambda: cls.__name__
        else:
            return lambda: instance.name

class MyClass:

    def __init__(self, name):
        self.name = name

    foo = MyDescriptor()

相关问题