【发布时间】:2016-09-04 07:57:57
【问题描述】:
想象一下下面的代码(单独看完全没用):
# define a property with additional methods
class P(property):
def __init__(self, name):
property.__init__(self,
fget=lambda self: self._get(name),
fset=lambda self, v: self._set(name, v))
self._name = name
def some_fn(self):
print('name: ' + self._name)
# define a class with two 'enhanced' properties
class C:
p1 = P('p1')
p2 = P('p2')
def __init__(self):
self._values = {}
def _get(self, name):
return self._values[name]
def _set(self, name, v):
self._values[name] = v
c = C()
c.p1 = 5
c.p2 = c.p1
print(c.p1, c.p2)
我只是用两个properties 创建了一个类C,它们有一个额外的方法some_fn()。
现在的问题是:你不能通过写c.p1.some_fn() 轻松调用some_fn(),因为你会先评估c.p1,这会导致一些值不再提供该方法。
我试图找到一些在certain property 的上下文中调用some_fn 的变通方法/方法,这不是它的价值,但我还不开心。
我的目标很简单:
我希望能够在没有样板的情况下读取/分配属性:
c.p1 = c.p2而不是c.p1.set(c.p2.get())我调用额外方法/函数的方式必须易于读/写
我想编写可以被
pylint、mypy等静态验证的代码,所以some_fn('c.p1') is not an option because it can't be checked whether 'c.p1' is a valid attribute of an existing objectc`。some_fn不必必须是一种方法。它可以是一个函数或任何其他在属性上下文中请求功能的方式我什至不需要真实
properties。任何其他写s.th的方式。 像c.p1 == c.p2一样(例如使用__getattr__/__setattr__)也可以,只要 get/set 操作仍然可跟踪。
我收集了一些代码来说明我在说什么:
# ==== What I want to do ==============
c.p1.some_fn() # <-- this is what I want to write but
# it's invalid since it evaluates to
# 5.some_fn()
some_fn(c.p1) # <-- something like this looks OK, too but
# it evalueates to some_fn(5) (useless)
# ==== These are options that came to mind but I'm not happy with ======
getattr(C, 'p1').some_fn() # <-- this works but it is ugly
some_fn("c.p1") # <-- this is possible, too but I can't
# check integrity statically (pylint/mypy)
c.p1.value = c.p2.value # <-- this is a valid approach but it
c.p1.some_fn() # increases
some_fn(c.p1) # (again) # <-- This can acutally work if you `inspect`
# the call stack inside `C._get()` but
# it's black magic and incredibly slow
with some_fn(): # <-- this can work when `some_fn` changes
c.p1 # some global state which get's evaluated
# inside `C._get()`
【问题讨论】:
-
你想让
some_fn这样的方法做什么?你为什么需要它们?您提出的使用c.p1.value之类的示例是唯一可以真正起作用的示例。您无法让c.p1评估为 5,同时还允许c.p1.some_fn()。听起来您需要自定义分配给属性的 值,而不是属性对象本身。
标签: python methods properties call