- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我可以看到在 Python 中拥有属性的两种非常相似的方式
(a) 属性(property)类别
class Location(object):
def __init__(self, longitude, latitude):
self.set_latitude(latitude)
self.set_longitude(longitude)
def set_latitude(self, latitude):
if not (-90 <= latitude <= 90):
raise ValueError('latitude was {}, but has to be in [-90, 90]'
.format(latitude))
self._latitude = latitude
def set_longitude(self, longitude):
if not (-180 <= longitude <= 180):
raise ValueError('longitude was {}, but has to be in [-180, 180]'
.format(longitude))
self._longitude = longitude
def get_longitude(self):
return self._latitude
def get_latitude(self):
return self._longitude
latitude = property(get_latitude, set_latitude)
longitude = property(get_longitude, set_longitude)
class Location(object):
def __init__(self, longitude, latitude):
self.latitude = latitude
self.longitude = latitude
@property
def latitude(self):
"""I'm the 'x' property."""
return self._latitude
@property
def longitude(self):
"""I'm the 'x' property."""
return self._longitude
@latitude.setter
def latitude(self, latitude):
if not (-90 <= latitude <= 90):
raise ValueError('latitude was {}, but has to be in [-90, 90]'
.format(latitude))
self._latitude = latitude
@longitude.setter
def longitude(self, longitude):
if not (-180 <= longitude <= 180):
raise ValueError('longitude was {}, but has to be in [-180, 180]'
.format(longitude))
self._longitude = longitude
>>> import py_compile
>>> py_compile.compile('test.py')
import test # (a)
import test2 # (b)
dis.dis(test)
dis.dis(test2)
test2
的输出感到非常困惑:
Disassembly of Location:
Disassembly of __init__:
13 0 LOAD_FAST 2 (latitude)
2 LOAD_FAST 0 (self)
4 STORE_ATTR 0 (latitude)
14 6 LOAD_FAST 2 (latitude)
8 LOAD_FAST 0 (self)
10 STORE_ATTR 1 (longitude)
12 LOAD_CONST 0 (None)
14 RETURN_VALUE
Disassembly of Location:
Disassembly of __init__:
13 0 LOAD_FAST 0 (self)
2 LOAD_ATTR 0 (set_latitude)
4 LOAD_FAST 2 (latitude)
6 CALL_FUNCTION 1
8 POP_TOP
14 10 LOAD_FAST 0 (self)
12 LOAD_ATTR 1 (set_longitude)
14 LOAD_FAST 1 (longitude)
16 CALL_FUNCTION 1
18 POP_TOP
20 LOAD_CONST 0 (None)
22 RETURN_VALUE
Disassembly of set_latitude:
17 0 LOAD_CONST 3 (-90)
2 LOAD_FAST 1 (latitude)
4 DUP_TOP
6 ROT_THREE
8 COMPARE_OP 1 (<=)
10 JUMP_IF_FALSE_OR_POP 18
12 LOAD_CONST 1 (90)
14 COMPARE_OP 1 (<=)
16 JUMP_FORWARD 4 (to 22)
>> 18 ROT_TWO
20 POP_TOP
>> 22 POP_JUMP_IF_TRUE 38
18 24 LOAD_GLOBAL 0 (ValueError)
26 LOAD_CONST 2 ('latitude was {}, but has to be in [-90, 90]')
28 LOAD_ATTR 1 (format)
30 LOAD_FAST 1 (latitude)
32 CALL_FUNCTION 1
34 CALL_FUNCTION 1
36 RAISE_VARARGS 1
19 >> 38 LOAD_FAST 1 (latitude)
40 LOAD_FAST 0 (self)
42 STORE_ATTR 2 (latitude)
44 LOAD_CONST 0 (None)
46 RETURN_VALUE
Disassembly of set_longitude:
22 0 LOAD_CONST 3 (-180)
2 LOAD_FAST 1 (longitude)
4 DUP_TOP
6 ROT_THREE
8 COMPARE_OP 1 (<=)
10 JUMP_IF_FALSE_OR_POP 18
12 LOAD_CONST 1 (180)
14 COMPARE_OP 1 (<=)
16 JUMP_FORWARD 4 (to 22)
>> 18 ROT_TWO
20 POP_TOP
>> 22 POP_JUMP_IF_TRUE 38
23 24 LOAD_GLOBAL 0 (ValueError)
26 LOAD_CONST 2 ('longitude was {}, but has to be in [-180, 180]')
28 LOAD_ATTR 1 (format)
30 LOAD_FAST 1 (longitude)
32 CALL_FUNCTION 1
34 CALL_FUNCTION 1
36 RAISE_VARARGS 1
24 >> 38 LOAD_FAST 1 (longitude)
40 LOAD_FAST 0 (self)
42 STORE_ATTR 2 (longitude)
44 LOAD_CONST 0 (None)
46 RETURN_VALUE
最佳答案
你总是想使用装饰器。其他语法没有优点,只有缺点。
装饰器的要点
那是因为装饰器语法是专门为避免其他语法而发明的。您找到的有关 name = property(...)
的任何示例多样性通常出现在早于装饰器的代码中。
装饰器语法是语法糖;表格
@decorator
def functionname(...):
# ...
def functionname(...):
# ...
functionname = decorator(functionname)
functionname
被分配两次(
def functionname(...)
部分创建一个函数对象并正常分配给
functionname
,但使用装饰器创建函数对象并直接传递给装饰器对象)。
The current method of applying a transformation to a function or method places the actual transformation after the function body. For large functions this separates a key component of the function's behavior from the definition of the rest of the function's external interface.
[...]
This becomes less readable with longer methods. It also seems less than pythonic to name the function three times for what is conceptually a single declaration.
The new syntax should
- [...]
- move from the end of the function, where it's currently hidden, to the front where it is more in your face
@property
def latitude(self):
# ...
@latitude.setter
def latitude(self, latitude):
# ...
def get_latitude(self):
# ...
def set_latitude(self, latitude):
# ...
latitude = property(get_latitude, set_latitude)
@property
装饰器将您装饰的函数对象替换为装饰结果(一个
property
实例),您还可以避免命名空间污染。无
@property
和
@<name>.setter
和
@<name>.deleter
,你必须在你的类定义中添加 3 个额外的、单独的名称,然后没有人会使用:
>>> [n for n in sorted(vars(Location)) if n[:2] != '__']
['get_latitude', 'get_longitude', 'latitude', 'longitude', 'set_latitude', 'set_longitude']
get_latitude
之间的区别感到困惑。 ,
latitude
和
set_latitude
,并且您最终会得到混合样式的代码,并且现在更难摆脱在类级别公开这些方法。
del get_latitude, set_latitude
紧跟在
latitude = property(...)
之后分配,但这是更多额外的代码来执行,没有真正的目的。
get_
前缀。和
set_
或以其他方式区分名称以创建
property()
来自他们的对象,这仍然是几乎所有不使用
@property
的代码的方式。装饰器语法最终命名访问器方法。
get_latitude
或
set_latitude
在名称中,而前一行使用了
object.latitude
. Python 属性新手可能并不总是清楚这两者是如何连接的,特别是如果他们错过了
latitude = property(...)
再往下线;看上面。
property
对象,当在类上访问时,已经通过
.fget
为您提供了对访问器的引用。 ,
.fset
和
.fdel
属性:
>>> Location.latitude
<property object at 0x10d1c3d18>
>>> Location.latitude.fget
<function Location.get_latitude at 0x10d1c4488>
>>> Location.latitude.fset
<function Location.set_latitude at 0x10d195ea0>
@<name>.getter
/
@<name>.setter
/
@<name>.deleter
子类中的语法,而不必记住创建新的
property
目的!
class SpecialLocation(Location):
def set_latitude(self, latitude):
# ...
property
捡起来目的。
class SpecialLocation(Location):
@Location.latitude.setter
def latitude(self, latitude):
# ...
SpecialLocation
然后给子类一个新的
property()
具有从
Location
继承的 getter 的实例,并使用新的二传手。
关于python - 与属性类相比,使用属性装饰器是否有优势?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52899509/
首先对WCF与WebService的定义进行概括,接着介绍了WCF的优势,最后就是对WCF与WebService两者的根本区别进行比较,具体内容如下 1、定义 1.WebService:严格来
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 5年前关闭。 Improve t
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 8 年前。 Improve
谁能告诉我将下一个脚本标记放在 元素之后和将它放在 元素之前有什么好处? (function (){ var script = document.createElement("script"); s
我最近遇到了一个 JavaScript 脚本,其中作者似乎试图避免在代码中使用字符串并将所有内容都分配给一个变量。 所以代替 document.addEventListener('click', (e
Scott Meyers 在“Effective Modern C++”中说表达式 Matrix sum = m1 + m2 + m3 + m4 (其中所有对象的类型均为 Matrix)“如果 ope
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
免责声明:我是网络开发的新手,所以请多多包涵... 堆栈:Angular 前端,后端的 Tornado(基于 python)网络服务器 我一直在使用 RxJs 和 WebSocket 成功地与后端通信
我一直在调查我的 Flutter 应用程序的 JSON 解析,并且有一个关于我无法解决的工厂构造函数的问题。我试图了解使用工厂构造函数与普通构造函数的优势。例如,我看到很多 JSON 解析示例,它们使
添加 SQL 后尝试打开 TadsQuery 时出现 5400 AE_INTERNAL_ERROR。当我将相同的 SQL 直接放在 TadsQuery 中时,没有错误。您的帮助文件指示我联系 Adva
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它. 8年前关闭。 Improve this
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 9 年前。 Improv
我想定义一个函数,当给定一个整数时,它将返回一个字符串。像这样: # Pseudocode function get_string(i) return my_string_array[i] end
我曾尝试在 Linux 和 Windows 上使用 DBD::Advantage,但没有成功。 Windows 版本附带了一个看似完整的安装程序,但它留下了 DBD-Advantage-8.10.ta
为什么说 NoSQL 在结构上比某些 SQL 数据库更快?假设我在某个 SQL 表的列上添加了一些索引。有人可以提供某种更快的查询吗? 我正在阅读有关 redis 的内容。 class User <
我的问题很简单:如果接口(interface)由单个类实现,那么使用接口(interface)有什么好处吗? 我一直认为只有当该接口(interface)有多个实现时,接口(interface)才是好
考虑这些(或多或少)等价的类型签名: f1 :: [a] -> Int -> a f2 :: Integral b => [a] -> b -> a f2 比 f1 更通用,这是一个很大的优势,但是
我们在 Scala 中部分应用了函数- def sum(a:Int,b:Int,c:Int) = a+b+c val partial1 = sum(1,_:Int,8) 我想知道使用部分应用函数的优点
你看下面的代码,我是如何使用 session 变量的;所以这三个问题是: 它们存放在哪里? (服务器或客户端) 它们对于每个网页访问者来说都是独一无二的吗? 我可以在完成工作后使用 ajax 或简单的
我知道这是一个常见问题,互联网上有关于此主题的资源,但我想从这个社区了解每个人在部署博客时对子域与子文件夹的想法(SEO 优势)。 谢谢。 最佳答案 我研究过一次,根据社区反馈以及权衡利弊,我会说去一
我是一名优秀的程序员,十分优秀!