如何创建返回类本身实例的静态类属性?

时间:2019-02-04 16:38:48

标签: python oop properties

我写了一个可以以任意精度处理整数的类(仅出于学习目的)。该类采用整数的字符串表示形式,并将其转换为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的实例。由于类型错误,该实例无法用于计算。

有没有办法解决这个问题?

2 个答案:

答案 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)

问题是相互矛盾的:staticproperty并非以这种方式并存。 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'

希望这会有所帮助!