我是oop和python的新手。我一直在尝试做一个简单的事情: 有一个名为Foo()的类,它包含一个名为x的变量,该变量最初设置为零。
>>>a = Foo()
>>>a.x
>>>0
现在我想给x一个新值,这样:
>>>p.x = 1983
现在x应该进行数学运算,例如1被添加到x。现在x是1984,所以现在当我调用x时:
>>> p.x
>>> 1984
程序还应检查x的值是否为负,如果为负,则应返回-1。 我这样做了,但是没用:(我说过应该在x上做一些数学运算,但运算本身并不重要)
class Foo():
x = 0
if x > 0:
x %= 100
elif x < 0:
x = -1
我现在真的不应该更新我提到的类变量。 非常感谢您的关注。
答案 0 :(得分:2)
假设您不需要实际的类属性(总在构造Foo
的实例以使用该属性,并且类属性既是公共的又是逻辑上可变的,这并不常见),解决方案是使x
a property
包裹一个 instance 属性,该属性在实例的__init__
初始化程序中为每个实例建立独立的值:
class Foo:
def __init__(self):
self._x = 0 # _x is a protected instance attr that the property uses behind the scenes
@property
def x(self): # getter for x is normal
return self._x
@x.setter
def x(self, newx): # setter for x massages the value before setting it
if newx >= 0: # Cheaper to handle 0 on same code path as > 0 so you needn't test < 0
newx %= 100
else:
newx = -1
self._x = newx
用法非常简单:
>>> myfoo = Foo()
>>> myfoo.x = 1983
>>> myfoo.x
83
>>> myfoo.x = -3748972983
>>> myfoo.x
-1
如果确实需要将其作为类属性并且必须在实例上可以访问,则解决方案会变得很丑陋,因为您需要a metaclass来提供property
类,以及类本身的其他属性,以将实例的访问权委派给类本身。
注意:我强烈不鼓励实际做此事,而不是做运动:
class FooMeta(type): # Inheriting from type makes metaclass
@property
def x(cls):
return cls._x
@x.setter
def x(cls, newx):
if newx >= 0:
newx %= 100
else:
newx = -1
cls._x = newx
class Foo(metaclass=FooMeta):
_x = 0
# Must make properties on class if instances are to "benefit" from class property
@property
def x(self):
return type(self).x
@x.setter
def x(self, newx):
type(self).x = newx
这可以使以下各项起作用:
>>> Foo.x # x exists on Foo itself, not just instances
>>> Foo.x = 1983
>>> Foo.x
83
>>> f = Foo()
>>> f.x # Accessible on instances too
83
>>> f.x = -234789
>>> f.x # Same behavior on instance
-1
>>> Foo.x # Changing instance changed class
答案 1 :(得分:1)
可能会有所帮助。您应该按照以下方式重构类定义
class Foo():
def __init__(self):
self.x=0
def check_x(self):
if self.x > 0:
return (self.x % 100)
elif self.x < 0:
return -1
p=Foo()
print(p.x) # 0
p.x=1983
p.check_x() # 83
检查负值
p.x=-100
p.check_x() # -1