Python:如何使属性私有化来阻止程序进入无限循环?(私人v/s公共属性)
我对python中的面向对象概念很幼稚。在阅读本文中的OOP概念时,我遇到了一个例子Python:如何使属性私有化来阻止程序进入无限循环?(私人v/s公共属性),python,python-3.x,class,oop,private,Python,Python 3.x,Class,Oop,Private,我对python中的面向对象概念很幼稚。在阅读本文中的OOP概念时,我遇到了一个例子 class P1: def __init__(self,x): self.x = x @property def x(self): return self.__x @x.setter def x(self, x): if x < 0: self.__x = 0 elif x
class P1:
def __init__(self,x):
self.x = x
@property
def x(self):
return self.__x
@x.setter
def x(self, x):
if x < 0:
self.__x = 0
elif x > 1000:
self.__x = 1000
else:
self.__x = x
e = P(x = 2100)
f = e.x*2
print(f)
2000
似乎我的程序首先调用了init方法,然后它从setter区域3到setter区域6连续来回运行。
有人能解释一下吗
属性是实现的对象。对于常见的描述符用例,它是一个方便的描述符。但是我们可以创建自己的描述符类型
从根本上说,描述符是实现\uuuuu get\uuuuu
、\uuuu set\uuuuu
或\uuu delete\uuuu
任意组合的任何python类型
当您执行某些\u对象时,将调用这些属性。某些\u属性
,某些\u对象。某些\u属性=值
,以及删除某些\u对象。某些\u属性
其中某些\u属性
是某些\u对象上的描述符。\uu类
<>所以,考虑一个具体的例子:
>>> class Foo:
... def __get__(self, obj, objtype):
... print('inside Foo.__get__')
... return 42
...
>>> class Bar:
... foo = Foo()
...
>>> bar = Bar()
>>> bar.foo
inside Foo.__get__
42
描述符截取属性访问、修改和删除类实例(该类将描述符作为属性),以允许各种有趣的内容
请注意,描述符属于以下类:
>>> vars(bar)
{}
>>> vars(Bar)
mappingproxy({'__module__': '__main__', 'foo': <__main__.Foo object at 0x1025272e8>, '__dict__': <attribute '__dict__' of 'Bar' objects>, '__weakref__': <attribute '__weakref__' of 'Bar' objects>, '__doc__': None})
但是我们可以控制它,我们可以实现
>>> class Foo:
... def __get__(self, obj, objtype):
... return 42
... def __set__(self, obj, val):
... print('nah-ah-ah')
...
...
>>> class Bar:
... foo = Foo()
...
>>> bar = Bar()
>>> bar.foo
42
>>> bar.foo = 99
nah-ah-ah
>>> bar.foo
42
属性
对象只允许您提供在使用属性时将被委托的函数。\uuuuu获取\uuuuuuuu
、属性。\uuuuuu设置\uuuuuuuuuu
和属性。docstrings的信息量很大,只需在python shell中使用帮助(属性)
:
class property(object)
| property(fget=None, fset=None, fdel=None, doc=None)
|
| Property attribute.
|
| fget
| function to be used for getting an attribute value
| fset
| function to be used for setting an attribute value
| fdel
| function to be used for del'ing an attribute
| doc
| docstring
|
| Typical use is to define a managed attribute x:
|
| class C(object):
| def getx(self): return self._x
| def setx(self, value): self._x = value
| def delx(self): del self._x
| x = property(getx, setx, delx, "I'm the 'x' property.")
|
| Decorators make defining new properties or modifying existing ones easy:
|
| class C(object):
| @property
| def x(self):
| "I am the 'x' property."
| return self._x
| @x.setter
| def x(self, value):
| self._x = value
| @x.deleter
| def x(self):
| del self._x
因此,无论您用@property.setter
装饰什么,您都可以想象get被传递到属性(fset=)
。现在,每当您的实例尝试设置x.some\u attribute=value
时,其中的某个属性是类x:
上的一个属性,调用属性时,您可以想象它会被调用x.some\u attribute=value
转换为x.some\u属性
因此,为了找到问题的关键,为什么无限递归,因为使用obj.x=val
,其中.x
是一个属性,将调用fset
,但是在fset中使用obj.x=val
,并且fset
会再次被调用,这是隐藏的递归
@decorator
语法是为了方便起见,始终首先接受getter,但您可以使用长格式方式仅提供setter:
>>> class Weird:
... def setx(self, value):
... self._x = value
... x = property(fset=setx)
...
>>> w = Weird()
>>> w.x = 'foo'
>>> w.x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: unreadable attribute
>>类:
... def setx(自身,值):
... self._x=值
... x=属性(fset=setx)
...
>>>w=奇怪的()
>>>w.x=‘foo’
>>>w.x
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:无法读取的属性
我强烈建议你阅读这本书。扰流板警报、classmethod
和staticmethod
都是描述符,Python如何神奇地将实例传递给方法也是描述符(也就是说,所有函数对象都是描述符,当被类上的实例访问时,\uuu get\uu
方法将实例作为第一个参数传递给函数本身。)它还显示了所有这些内容的Python实现,包括如何在纯Python中实现属性
“为什么要在这里设置魔法私有属性,使程序
没有陷入无限循环”
实际上,这不是一个使用双下划线名称混乱的好地方。除了一个细节之外,我喜欢那个教程。您可以使用一个下划线,或者任何有效的python标识符(除了属性占用的标识符),您将看到相同的效果
属性是一个实现的对象。对于常见的描述符用例,它是一个方便的描述符。但是我们可以创建自己的描述符类型
从根本上说,描述符是实现\uuuuu get\uuuuu
、\uuuu set\uuuuu
或\uuu delete\uuuu
任意组合的任何python类型
当您执行某些\u对象时,将调用这些属性。某些\u属性
,某些\u对象。某些\u属性=值
,以及删除某些\u对象。某些\u属性
其中某些\u属性
是某些\u对象上的描述符。\uu类
<>所以,考虑一个具体的例子:
>>> class Foo:
... def __get__(self, obj, objtype):
... print('inside Foo.__get__')
... return 42
...
>>> class Bar:
... foo = Foo()
...
>>> bar = Bar()
>>> bar.foo
inside Foo.__get__
42
描述符截取属性访问、修改和删除类实例(该类将描述符作为属性),以允许各种有趣的内容
请注意,描述符属于以下类:
>>> vars(bar)
{}
>>> vars(Bar)
mappingproxy({'__module__': '__main__', 'foo': <__main__.Foo object at 0x1025272e8>, '__dict__': <attribute '__dict__' of 'Bar' objects>, '__weakref__': <attribute '__weakref__' of 'Bar' objects>, '__doc__': None})
但是我们可以控制它,我们可以实现
>>> class Foo:
... def __get__(self, obj, objtype):
... return 42
... def __set__(self, obj, val):
... print('nah-ah-ah')
...
...
>>> class Bar:
... foo = Foo()
...
>>> bar = Bar()
>>> bar.foo
42
>>> bar.foo = 99
nah-ah-ah
>>> bar.foo
42
属性
对象只允许您提供在使用属性时将被委托的函数。属性。属性。设置属性。属性。删除属性。文档字符串信息量很大,只需在python shell中使用帮助(属性)
:
class property(object)
| property(fget=None, fset=None, fdel=None, doc=None)
|
| Property attribute.
|
| fget
| function to be used for getting an attribute value
| fset
| function to be used for setting an attribute value
| fdel
| function to be used for del'ing an attribute
| doc
| docstring
|
| Typical use is to define a managed attribute x:
|
| class C(object):
| def getx(self): return self._x
| def setx(self, value): self._x = value
| def delx(self): del self._x
| x = property(getx, setx, delx, "I'm the 'x' property.")
|
| Decorators make defining new properties or modifying existing ones easy:
|
| class C(object):
| @property
| def x(self):
| "I am the 'x' property."
| return self._x
| @x.setter
| def x(self, value):
| self._x = value
| @x.deleter
| def x(self):
| del self._x
因此,无论您用@property.setter
装饰什么,您都可以想象get传递给