我写了一个类,能够处理任意精度的整数(只是为了学习的目的)。类需要一个整数的字符串表示,并将其转换成用于进一步计算的BigInt
的实例。
很多时候,你需要的数字零和一,所以我认为这将是有益的,如果这个类可以返回这些。我试过如下:
class BigInt():
zero = BigInt("0")
def __init__(self, value):
####yada-yada####
这是行不通的。错误:“名称‘BigInt有’没有定义”
然后,我试过如下:
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
的一个实例,而不是BigInt
。该实例不能使用,因为错误类型的计算。
有没有解决这个问题的方法吗?
静态属性...?我们称之为静态属性的“属性”。这是不是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:
...
现在的问题是矛盾的:static
和property
不以这种方式走在一起。在Python静态属性只是那些只分配一次,而语言本身包括大量的这些。 (大多数字符串埋葬,所有整数<一定值是预先构建的等例如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
s可以像缓存和流线型构造/单储存的形式是有用的。 (例如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'
希望这可以帮助!