python - 在python中对类内的变量进行操作
问题描述
我是 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
我现在真的不知道我应该如何更新我提到的类变量。非常感谢您的关注。
解决方案
假设您不需要实际的类属性(Foo
无论如何,您总是在构建一个实例来使用该属性,并且类属性既是公共的又是逻辑可变的并不常见),正确的解决方案是制作x
一个property
包装实例属性,每个实例都有独立的值,在__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
如果它确实需要是一个类属性并且它必须可以在实例上访问,那么解决方案会变得很难看,因为您需要一个元类来为类提供property
s,并在类本身上提供其他属性来将实例的访问权限委托给类本身.
注意:我强烈不鼓励将其作为练习以外的任何其他方式进行:
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
推荐阅读
- scala - 在数据框的一行中创建一个结构字段
- node.js - 包括模型,除非属性为空 - 节点序列化
- apache - 使用 .htaccess 将子目录重定向到其他目录
- java - 如何将错误从执行程序通道路由到错误通道?
- python - 如何使用 tkinter 在 python 中随机化按钮位置?
- linux - Ubuntu 16.04 给出 AT&T 错误:“分段错误(核心转储)”(AT&T 64 位)
- php - Codeigniter - 显示有条件的数字
- dialogflow-es - 如何在 Dialogflow 中接收用户的数字序列?
- java - Spring Data Rest 持久化注解
- javascript - 错误:未找到 GoogleCardLayout2 的组件工厂