Nli*_*tis 55 python attributes declaration python-3.x
我正在学习python,虽然我认为我得到了Python的整个概念和概念,但今天我偶然发现了一段我并不完全理解的代码:
假设我有一个应该定义Circles但缺少一个body的类:
class Circle():
pass
Run Code Online (Sandbox Code Playgroud)
由于我没有定义任何属性,我该怎么做:
my_circle = Circle()
my_circle.radius = 12
Run Code Online (Sandbox Code Playgroud)
奇怪的是Python接受上述语句.我不明白为什么Python没有引发undefined name error
.我明白通过动态类型我只需要随时将变量绑定到对象,但是类中是否不radius
存在Circle
允许我这样做的属性?
编辑:你的答案中有很多精彩的信息!谢谢大家的所有精彩答案!遗憾的是我只能将一个标记为答案.
小智 47
一个主要原则是没有声明这样的东西.也就是说,你永远不会声明"这个类有一个方法foo"或"这个类的实例有一个属性栏",更不用说关于要存储在那里的对象类型的声明了.您只需定义一个方法,属性,类等,然后添加它.正如JBernardo指出的那样,任何__init__
方法都可以做同样的事情.任意限制创建具有名称的方法的新属性是没有多大意义的__init__
.并且存储一个__init__
实际上没有该名称的函数(例如装饰器)有时很有用,而这样的限制会破坏它.
现在,这并非普遍适用.内置类型将此功能省略为优化.通过__slots__
,您还可以在用户定义的类上禁止此操作.但这只是一个空间优化(不需要每个对象的字典),而不是正确的东西.
如果你想要一个安全网,那么太糟糕了.Python没有提供一个,你不能合理地添加一个,最重要的是,它会被拥抱该语言的Python程序员所避开(阅读:几乎所有你想要使用的程序员).测试和纪律,仍然有很长的路要走,以确保正确性.__init__
如果可以避免的话,不要使用自由来弥补属性,并进行自动化测试.AttributeError
由于这样的欺骗,我很少有或者出现逻辑错误,而且那些发生的事情几乎都被测试所捕获.
Len*_*bro 38
只是为了澄清这里讨论中的一些误解.这段代码:
class Foo(object):
def __init__(self, bar):
self.bar = bar
foo = Foo(5)
Run Code Online (Sandbox Code Playgroud)
这段代码:
class Foo(object):
pass
foo = Foo()
foo.bar = 5
Run Code Online (Sandbox Code Playgroud)
是完全相同的.确实没有区别.它完全一样.这种区别在于,在第一种情况下,它被封装,并且很明显bar属性是Foo类型对象的正常部分.在第二种情况下,不清楚是否如此.
在第一种情况下,你不能创建一个没有bar属性的Foo对象(嗯,你可能,但不容易),在第二种情况下,除非你设置它,否则Foo对象将没有bar属性.
因此,尽管代码在编程上是等效的,但它在不同的情况下使用.
kin*_*all 19
Python允许您在几乎任何实例(或类)上存储任何名称的属性.可以通过在C中编写类(如内置类型)或使用__slots__
仅允许某些名称的类来阻止此操作.
它起作用的原因是大多数实例将其属性存储在字典中.是的,像你定义的常规Python字典{}
.字典存储在名为的实例属性中__dict__
.事实上,有些人说"课程只是词典的语法糖".也就是说,您可以使用带有字典的类来完成所有操作; 课程只是让它变得更容易.
您已经习惯了静态语言,您必须在编译时定义所有属性.在Python中,类定义是执行的,而不是编译的; 类就像任何其他类一样是对象; 添加属性就像在字典中添加项一样简单.这就是Python被认为是动态语言的原因.
Mar*_*ers 17
不,python是这样灵活的,它不强制你可以存储在用户定义的类上的属性.
但是,有一个技巧,使用类定义上的__slots__
属性将阻止您创建未在__slots__
序列中定义的其他属性:
>>> class Foo(object):
... __slots__ = ()
...
>>> f = Foo()
>>> f.bar = 'spam'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'bar'
>>> class Foo(object):
... __slots__ = ('bar',)
...
>>> f = Foo()
>>> f.bar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: bar
>>> f.bar = 'spam'
Run Code Online (Sandbox Code Playgroud)
它创建了一个radius
数据成员my_circle
.
如果你问过my_circle.radius
它会抛出异常:
>>> print my_circle.radius # AttributeError
Run Code Online (Sandbox Code Playgroud)
有趣的是,这不会改变班级; 只是那个例子.所以:
>>> my_circle = Circle()
>>> my_circle.radius = 5
>>> my_other_circle = Circle()
>>> print my_other_circle.radius # AttributeError
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
25189 次 |
最近记录: |