我写了一个可以以任意精度处理整数的类(仅出于学习目的)。该类采用整数的字符串表示形式,并将其转换为PUBLIC_URL=https://<my-s3-bucket_url>
的实例以进行进一步的计算。
通常您需要数字零和一个,所以我认为如果班级可以返回这些数字会很有帮助。我尝试了以下方法:
BigInt
这不起作用。错误:“未定义名称'BigInt'”
然后我尝试了以下操作:
class BigInt():
zero = BigInt("0")
def __init__(self, value):
####yada-yada####
这实际上效果很好。我不喜欢的是class BigInt():
__zero = None
@staticmethod
def zero():
if BigInt.__zero is None:
BigInt.__zero = BigInt('0')
return BigInt.__zero
def __init__(self, value):
####yada-yada####
是一种方法(因此必须用zero
来调用),这是违反直觉的,因为它应该只引用固定值。
因此,我尝试将BigInt.zero()
更改为属性,但是由于使用了装饰器,因此编写zero
返回类BigInt.zero
而不是property
的实例。由于类型错误,该实例无法用于计算。
有没有办法解决这个问题?
答案 0 :(得分:6)
静态属性...?我们称静态属性为“属性”。这不是Java,Python是一种动态类型的语言,这样的构造确实会使事情变得过于复杂。
只需设置一个类属性即可:
class BigInt:
def __init__(self, value):
...
BigInt.zero = BigInt("0")
如果您希望将其完全封装在类块中,请使用类装饰器(但要注意,这只是编写相同内容的一种更理想的方式)。
def add_zero(cls):
cls.zero = cls("0")
return cls
@add_zero
class BigInt:
...
答案 1 :(得分:1)
问题是相互矛盾的:static
和property
并非以这种方式并存。 Python中的静态属性只是仅分配一次的语言,而语言本身包含了大量此类属性。 ( Most 字符串是连续的,所有小于某个值的整数都是预先构造的,例如the string
module。)。最简单的方法是在构造后静态分配属性,如wim所示:
class Foo:
...
Foo.first = Foo()
...
或者,正如他进一步建议的那样,使用类装饰器执行分配,其功能与上述相同。装饰器实际上是一个函数,该函数被赋予“装饰”函数作为参数,并且必须返回一个函数以有效替换原始函数。这可能是原始功能,例如,经过了一些注释的修改,或者可能是完全不同的功能。原始(装饰)函数可能会或可能不会被装饰者适当地调用。
def preload(**values):
def inner(cls):
for k, v in values.items():
setattr(cls, k, cls(v))
return cls
return inner
然后可以动态使用它:
@preload(zero=0, one=1)
class Foo:
...
如果目的是在公共整数值上节省一些时间,则将defaultdict
映射到构造的BigInt
的整数可以作为缓存和简化构造/单例存储的一种形式。 (例如BigInt.numbers[27]
)
但是,在课堂上使用@property
的问题引起了我的兴趣,因此我做了一些深入的研究。如果将对象模型层次结构中的属性平移到元类,则完全有可能在类级别使用“ descriptor protocol objects”(@property
装饰器返回)。
class Foo(type):
@property
def bar(cls):
print("I'm a", cls)
return 27
class Bar(metaclass=Foo):
...
>>> Bar.bar
I'm a <class '__main__.Bar'>
<<< 27
值得注意的是,实例无法访问此属性:
>>> Bar().bar
AttributeError: 'Bar' object has no attribute 'bar'
希望这会有所帮助!