Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Python中从类内部访问classmethod_Python_Class Members - Fatal编程技术网

如何在Python中从类内部访问classmethod

如何在Python中从类内部访问classmethod,python,class-members,Python,Class Members,我想用Python创建一个类来管理所有静态成员。这些成员应该在定义类的过程中初始化。由于稍后将需要重新初始化静态成员,因此我将把这段代码放入一个classmethod中 我的问题是:如何从类内部调用此classmethod class Test(): # static member x = None # HERE I WOULD LOVE TO CALL SOMEHOW static_init! # initialize static member in cla

我想用Python创建一个类来管理所有静态成员。这些成员应该在定义类的过程中初始化。由于稍后将需要重新初始化静态成员,因此我将把这段代码放入一个classmethod中

我的问题是:如何从类内部调用此classmethod

class Test():
    # static member
    x = None
    # HERE I WOULD LOVE TO CALL SOMEHOW static_init!

    # initialize static member in classmethod, so that it can be 
    #reinitialized later on again    
    @classmethod
    def static_init(cls):
        cls.x = 10
感谢您的帮助

提前感谢,,
Volker

您可以通过附加类名来调用类方法:

class.method
在您的代码中,这样的内容就足够了:

Test.static_init()
您也可以这样做:

static_init(Test)
要在类内调用它,请让代码执行以下操作:

Test.static_init()
我的工作代码:

class Test(object):

    @classmethod
    def static_method(cls):
        print("Hello")

    def another_method(self):
        Test.static_method()

Test()。第一个是应用博格设计模式。第二种方法是放弃类方法,改用模块级函数。这似乎可以解决您的问题:

def _test_static_init(value):
    return value, value * 2

class Test:
    x, y = _test_static_init(20)

if __name__ == "__main__":
    print Test.x, Test.y

旧的、不正确的答案: 下面是一个例子,我希望它能有所帮助:

class Test:
    x = None

    @classmethod
    def set_x_class(cls, value):
        Test.x = value

    def set_x_self(self):
        self.__class__.set_x_class(10)

if __name__ == "__main__":
    obj = Test()
    print Test.x
    obj.set_x_self()
    print Test.x
    obj.__class__.set_x_class(15)
    print Test.x

无论如何,NlightNFotis的答案是更好的:在访问类方法时使用类名。它使代码不那么晦涩。

在示例中执行
x=10
时,不仅类不存在,而且类方法也不存在

Python中的执行自上而下。如果
x=10
位于classmethod之上,则无法在该点访问classmethod,因为它尚未定义

即使可以运行classmethod,也没关系,因为类还不存在,所以classmethod无法引用它。在整个类块运行之后才创建该类,因此当您在类块内部时,就没有类了

如果您想考虑一些类初始化,以便以后可以按照您描述的方式重新运行它,请使用类装饰器。类装饰器在创建类之后运行,因此它可以很好地调用classmethod

>>> def deco(cls):
...     cls.initStuff()
...     return cls
>>> @deco
... class Foo(object):
...     x = 10
...     
...     @classmethod
...     def initStuff(cls):
...         cls.x = 88
>>> Foo.x
88
>>> Foo.x = 10
>>> Foo.x
10
>>> Foo.initStuff() # reinitialize
>>> Foo.x
88

您不能在
定义中调用
类方法
,因为该类尚未完全定义,因此没有任何东西可以将该方法作为其第一个
cls
参数传递……这是一个典型的鸡和蛋问题。但是,您可以通过在元类中重载
\uuuu new\uuuuu()
方法,并在创建类后从该方法调用classmethod来克服此限制,如下所示:

class Test(object):
    # nested metaclass definition
    class __metaclass__(type):
        def __new__(mcl, classname, bases, classdict):
            cls = type.__new__(mcl, classname, bases, classdict)  # creates class
            cls.static_init()  # call the classmethod
            return cls

    x = None

    @classmethod
    def static_init(cls):  # called by metaclass when class is defined
        print("Hello")
        cls.x = 10

print Test.x
输出:

你好 10
这似乎是一个合理的解决方案:

from __future__ import annotations
from typing import ClassVar, Dict
import abc
import string


class Cipher(abc.ABC):
    @abc.abstractmethod
    def encrypt(self, plaintext: str) -> str:
        pass

    @abc.abstractmethod
    def decrypt(self, ciphertext: str) -> str:
        pass


class RotateCipher(Cipher, abc.ABC):
    @staticmethod
    def rotate(n: int) -> str:
        return string.ascii_uppercase[n:] + string.ascii_uppercase[:n]


class VigenereCipher(RotateCipher):
    _TABLE: ClassVar[Dict[str, str]] = dict({(chr(i + ord("A")), RotateCipher.rotate(i)) for i in range(26)})

    def encrypt(self, plaintext: str) -> str:
        pass

    def decrypt(self, plaintext: str) -> str:
        pass


vc = VigenereCipher()
该方法现在是密码的静态方法,不引用类之外的任何内容。如果您不希望人们单独使用它,您可以选择命名为RotateCipher
\u RotateCipher

注意:我在3.7上运行时删除了
Final
,但是在阅读了Final上的文档之后,我认为这不会影响解决方案?还添加了问题缺少的
字符串的导入。最后为抽象方法添加了一个实现,或者,也可以让VigenereCipher从
abc.abc
继承

class Person:
    def __init__(self,a,b):
            self.first = a
            self.second = b

    @classmethod
    def add(cls,a,b):
        return a+b
    
    def __repr__(self):
        return ('{}'.format(Person.add(self.first,self.second)))
    
p = Person(10,20)
print(p)

o/p : 30

别理我的大脑打嗝!你想这样做的原因是什么?好吧,对我来说重要的是,我能够在以后再次进行初始化。当然,这在x=10的情况下是没有意义的,但是在真正的应用程序中。我将加载一些XML文档,这些文档可以在应用程序运行时更改。不幸的是,这些文档似乎在类外工作。我刚刚尝试过:class Test():#static member x=None Test.static_init()#在classmethod中初始化静态成员,以便稍后可以#重新初始化@classmethod def static_init(cls):cls.x=10如果name==“main”:print(Test.x)Result:Test.static_init()NameError:name'Test'未定义#当我尝试从类内部使用Test.static_init()或static_init(Test)时,在定义classmethod之前,我收到一个错误:NameError:name'static_init'未定义defined@user1907681是的,伙计,这是因为python遵循自上而下的方法。这意味着,如果您在实际执行
def
之前尝试执行
Test.static_init()
,那么
static_init()
对于程序的其余部分来说是未知的,因此出现
名称错误是正常的。但是我得到了相同的名称错误:class Test():#静态成员x=None#在classmethod中初始化静态成员,以便稍后可以再次重新初始化@classmethod def static_init(cls):cls.x=10 Test.static_init(),不幸的是,这并不能解决我的问题。我知道如何从类外访问classmethod。但是我希望有一个类似于Java中的静态初始化器的东西,它调用一个静态方法,以后可以再次调用。看看Borg设计模式。是的,Borg设计模式或另一个单例模式解决方案可以解决我的问题,“它使你的代码不那么晦涩”,它还打破了子类化来覆盖classmethod。哇,这是一个优雅的解决方案!我从一个模块级函数开始解决我的问题,但这是一个通用的方法@user1907681我不相信你想走这条路线,但我不知道你的确切问题,所以不能确定。。。但是,这绝对是实现这一点的最具Python风格的方式(有很好的解释)+1最好从init调用initStuff,而不是依赖创建者来调用它。这就解决了原始海报的“这里我想称之为静态”的问题要求。@steveayre:从
\uuuu init\uuu
调用它意味着