如何从 class 变量引用静态方法
How to reference static method from class variable
鉴于 class
from __future__ import annotations
from typing import ClassVar, Dict, Final
import abc
class Cipher(abc.ABC):
@abc.abstractmethod
def encrypt(self, plaintext: str) -> str:
pass
@abc.abstractmethod
def decrypt(self, ciphertext: str) -> str:
pass
class VigenereCipher(Cipher):
@staticmethod
def rotate(n: int) -> str:
return string.ascii_uppercase[n:] + string.ascii_uppercase[:n]
_TABLE: Final[ClassVar[Dict[str, str]]] = dict({(chr(i + ord("A")), rotate(i)) for i in range(26)})
编译失败(使用 3.8.0)
../cipher.py:19: in <module>
class VigenereCipher(Cipher):
../cipher.py:24: in VigenereCipher
_TABLE: Final[ClassVar[Dict[str, str]]] = dict({(chr(i + ord("A")), rotate(i)) for i in range(26)})
../cipher.py:24: in <setcomp>
_TABLE: Final[ClassVar[Dict[str, str]]] = dict({(chr(i + ord("A")), rotate(i)) for i in range(26)})
E NameError: name 'rotate' is not defined
然而,根据this post,rotate
应该是可以解析的。请注意,使用 class name VigenereCipher
进行限定也不起作用,因为它找不到 VigenereCipher
(有道理,因为我们正在定义它)。
我可以使 rotate
成为模块级方法,这很有效,但我真的不想这样做,因为它只在 VigenereCipher
中需要。
也尝试 this 回答但没有成功。
从这里引发错误:
_TABLE: Final[ClassVar[Dict[str, str]]] = dict({(chr(i + ord("A")), rotate(i)) for i in range(26)})
您正在尝试引用位于 class 命名空间中的变量 rotate
。然而 python 推导式有自己的范围,没有简单的方法将它与 class 命名空间连接起来。在理解评估时没有闭包或全局变量 rotate
- 因此 NameError
被调用。上面的代码等于你的代码:
def _create_TABLE():
d = {}
for i in range(26):
d[chr(i + ord("A"))] = rotate(i) # -> NameError('rotate')
return d
_TABLE: Final[ClassVar[Dict[str, str]]] = dict(_create_TABLE())
del _create_TABLE
How to reference static method from class variable
python中的一个class变量是一些对象,所以它可以引用你程序中的任何对象。这里有一些你可以遵循的习语:
方法一:
class VigenereCipher(Cipher):
@staticmethod
def rotate(n: int) -> str:
return string.ascii_uppercase[n:] + string.ascii_uppercase[:n]
_TABLE: Final[ClassVar[Dict[str, str]]]
VigenereCipher._TABLE = {chr(i + ord("A")): VigenereCipher.rotate(i) for i in range(26)}
方法二:
class VigenereCipher(Cipher):
@staticmethod
def rotate(n: int) -> str:
return string.ascii_uppercase[n:] + string.ascii_uppercase[:n]
_TABLE: Final[ClassVar[Dict[str, str]]] = (
lambda r=rotate.__func__: {chr(i + ord("A")): r(i) for i in range(26)})()
方法三:
class VigenereCipher(Cipher):
@staticmethod
def rotate(n: int) -> str:
return string.ascii_uppercase[n:] + string.ascii_uppercase[:n]
_TABLE: Final[ClassVar[Dict[str, str]]] = dict(zip(
(chr(i + ord("A")) for i in range(26)),
map(rotate.__func__, range(26)),
))
方法四:
class VigenereCipher(Cipher):
@staticmethod
def rotate(n: int) -> str:
return string.ascii_uppercase[n:] + string.ascii_uppercase[:n]
_TABLE: Final[ClassVar[Dict[str, str]]] = {
chr(i + ord("A")): r(i) for r in (rotate.__func__,) for i in range(26)}
还有一些方法基于:
locals
function;
- metaclasses;
__init__subclass__
method;
- descriptor's
__set_name__
;
- stack frames;
- 使用
global
关键字。
您可以在相关的topic中找到更详细的答案
鉴于 class
from __future__ import annotations
from typing import ClassVar, Dict, Final
import abc
class Cipher(abc.ABC):
@abc.abstractmethod
def encrypt(self, plaintext: str) -> str:
pass
@abc.abstractmethod
def decrypt(self, ciphertext: str) -> str:
pass
class VigenereCipher(Cipher):
@staticmethod
def rotate(n: int) -> str:
return string.ascii_uppercase[n:] + string.ascii_uppercase[:n]
_TABLE: Final[ClassVar[Dict[str, str]]] = dict({(chr(i + ord("A")), rotate(i)) for i in range(26)})
编译失败(使用 3.8.0)
../cipher.py:19: in <module>
class VigenereCipher(Cipher):
../cipher.py:24: in VigenereCipher
_TABLE: Final[ClassVar[Dict[str, str]]] = dict({(chr(i + ord("A")), rotate(i)) for i in range(26)})
../cipher.py:24: in <setcomp>
_TABLE: Final[ClassVar[Dict[str, str]]] = dict({(chr(i + ord("A")), rotate(i)) for i in range(26)})
E NameError: name 'rotate' is not defined
然而,根据this post,rotate
应该是可以解析的。请注意,使用 class name VigenereCipher
进行限定也不起作用,因为它找不到 VigenereCipher
(有道理,因为我们正在定义它)。
我可以使 rotate
成为模块级方法,这很有效,但我真的不想这样做,因为它只在 VigenereCipher
中需要。
也尝试 this 回答但没有成功。
从这里引发错误:
_TABLE: Final[ClassVar[Dict[str, str]]] = dict({(chr(i + ord("A")), rotate(i)) for i in range(26)})
您正在尝试引用位于 class 命名空间中的变量 rotate
。然而 python 推导式有自己的范围,没有简单的方法将它与 class 命名空间连接起来。在理解评估时没有闭包或全局变量 rotate
- 因此 NameError
被调用。上面的代码等于你的代码:
def _create_TABLE():
d = {}
for i in range(26):
d[chr(i + ord("A"))] = rotate(i) # -> NameError('rotate')
return d
_TABLE: Final[ClassVar[Dict[str, str]]] = dict(_create_TABLE())
del _create_TABLE
How to reference static method from class variable
python中的一个class变量是一些对象,所以它可以引用你程序中的任何对象。这里有一些你可以遵循的习语:
方法一:
class VigenereCipher(Cipher):
@staticmethod
def rotate(n: int) -> str:
return string.ascii_uppercase[n:] + string.ascii_uppercase[:n]
_TABLE: Final[ClassVar[Dict[str, str]]]
VigenereCipher._TABLE = {chr(i + ord("A")): VigenereCipher.rotate(i) for i in range(26)}
方法二:
class VigenereCipher(Cipher):
@staticmethod
def rotate(n: int) -> str:
return string.ascii_uppercase[n:] + string.ascii_uppercase[:n]
_TABLE: Final[ClassVar[Dict[str, str]]] = (
lambda r=rotate.__func__: {chr(i + ord("A")): r(i) for i in range(26)})()
方法三:
class VigenereCipher(Cipher):
@staticmethod
def rotate(n: int) -> str:
return string.ascii_uppercase[n:] + string.ascii_uppercase[:n]
_TABLE: Final[ClassVar[Dict[str, str]]] = dict(zip(
(chr(i + ord("A")) for i in range(26)),
map(rotate.__func__, range(26)),
))
方法四:
class VigenereCipher(Cipher):
@staticmethod
def rotate(n: int) -> str:
return string.ascii_uppercase[n:] + string.ascii_uppercase[:n]
_TABLE: Final[ClassVar[Dict[str, str]]] = {
chr(i + ord("A")): r(i) for r in (rotate.__func__,) for i in range(26)}
还有一些方法基于:
locals
function;- metaclasses;
__init__subclass__
method;- descriptor's
__set_name__
; - stack frames;
- 使用
global
关键字。
您可以在相关的topic中找到更详细的答案