Python 使用哪种方法:类变量与类方法?

Python 使用哪种方法:类变量与类方法?,python,Python,作为下面的一个玩具示例,它们都创建了相同的类(尽管一个使用Foo.spam(),另一个使用Foo.spam来获取值)。我的问题是,选择其中一个的标准是什么?如果需要频繁访问垃圾邮件,由于函数开销,最好使用第二类实现?还有别的吗 class Foo(object): def __init__(self, a): self.a = "init" @classmethod def spam(cls, value=2): return value

作为下面的一个玩具示例,它们都创建了相同的类(尽管一个使用
Foo.spam()
,另一个使用
Foo.spam
来获取值)。我的问题是,选择其中一个的标准是什么?如果需要频繁访问
垃圾邮件
,由于函数开销,最好使用第二类实现?还有别的吗

class Foo(object):
    def __init__(self, a):
        self.a = "init"
    @classmethod
    def spam(cls, value=2):
        return value + 1
Foo.spam() # -> 3
Foo.spam(3) #-> 4

class Foo(object):
    spam = 3
    def __init__(self, a):
        self.a = "init"
Foo.spam  #-> 3
Foo.spam = 4
Foo.spam  #-> 4

如果该方法只返回属性值而不执行任何操作,则只使用该属性


然而,您的示例非常奇怪,因为您正在传递想要返回的值。如果您只需要数字3,则不需要使用
Foo.spam(3)
Foo.spam=3
;只需使用数字3。

如果该方法只返回属性值而不执行任何操作,则只需使用属性


然而,您的示例非常奇怪,因为您正在传递想要返回的值。如果您只需要数字3,则不需要使用
Foo.spam(3)
Foo.spam=3
;只需使用数字3即可。

我认为这两种方法都不符合pythonical的要求(为class属性指定一个默认值)。你为什么不干脆这么做

class Foo(object):
    def __init__(self, a = 'init'):
        self.a = a
        self.spam = 2
然后:

>>> a_foo = Foo()
>>> a_foo.spam
2
>>> a_foo.spam = 3
>>> a_foo.spam
3
如果通过静态类属性(第二个示例)执行此操作,则根据分配/访问它的方式,可以获得非常不同的行为:

class Foo(object):
    spam = 2
    def __init__(self, a = 'init'):
        self.a = a
然后:

>>> a_foo1 = Foo()
>>> a_foo2 = Foo()
>>> a_foo1.spam
2
>>> a_foo2.spam
2
>>> Foo.spam = 3
>>> a_foo1.spam
3
>>> a_foo2.spam
3

# But now they'll diverge
>>> a_foo1.spam = 5
>>> a_foo1.spam
5
>>> a_foo2.spam
3
>>> Foo.spam = 2
>>> a_foo1.spam
5
>>> a_foo2.spam
2
如果您试图使修改任何实例的
spam
副本可以修改实例的所有
spam
副本,则应使用与静态属性组合的属性

class Foo(object):
    _spam = 2
    def __init__(self, a = 'init'):
        self.a = a

    @property
    def spam(self):
        return Foo._spam

    @spam.setter
    def spam(self, value)
        Foo._spam = value

>>> a_foo1 = Foo()
>>> a_foo2 = Foo()
>>> a_foo1.spam
2
>>> a_foo2.spam
2
>>> a_foo1.spam = 3
>>> a_foo2.spam
3

尽管这种单例属性行为有点危险,有些人可能会认为它是反模式的,因为类的大多数用户并不期望修改一个实例的属性来修改所有实例的属性。这样做肯定需要有一个很好的理由。

我不认为这两种方法在pythonical上都是正确的(为class属性指定一个默认值)。你为什么不干脆这么做

class Foo(object):
    def __init__(self, a = 'init'):
        self.a = a
        self.spam = 2
然后:

>>> a_foo = Foo()
>>> a_foo.spam
2
>>> a_foo.spam = 3
>>> a_foo.spam
3
如果通过静态类属性(第二个示例)执行此操作,则根据分配/访问它的方式,可以获得非常不同的行为:

class Foo(object):
    spam = 2
    def __init__(self, a = 'init'):
        self.a = a
然后:

>>> a_foo1 = Foo()
>>> a_foo2 = Foo()
>>> a_foo1.spam
2
>>> a_foo2.spam
2
>>> Foo.spam = 3
>>> a_foo1.spam
3
>>> a_foo2.spam
3

# But now they'll diverge
>>> a_foo1.spam = 5
>>> a_foo1.spam
5
>>> a_foo2.spam
3
>>> Foo.spam = 2
>>> a_foo1.spam
5
>>> a_foo2.spam
2
如果您试图使修改任何实例的
spam
副本可以修改实例的所有
spam
副本,则应使用与静态属性组合的属性

class Foo(object):
    _spam = 2
    def __init__(self, a = 'init'):
        self.a = a

    @property
    def spam(self):
        return Foo._spam

    @spam.setter
    def spam(self, value)
        Foo._spam = value

>>> a_foo1 = Foo()
>>> a_foo2 = Foo()
>>> a_foo1.spam
2
>>> a_foo2.spam
2
>>> a_foo1.spam = 3
>>> a_foo2.spam
3

尽管这种单例属性行为有点危险,有些人可能会认为它是反模式的,因为类的大多数用户并不期望修改一个实例的属性来修改所有实例的属性。这样做肯定需要有一个很好的理由。

您能提供一个更清晰的用例吗?这两个示例都没有对您想要实现的目标提供足够清晰的概念,尤其是,在您传入
3
之后,对于未来的访问,示例的行为非常不同。相关:您能提供更清晰的用例吗?这两个示例都没有提供您想要实现的目标的足够清晰的概念,特别是,在您传入
3
后,这些示例对于将来的访问有非常不同的行为。相关: