gpt4 book ai didi

python - 如何向现有的 python 函数添加一行代码

转载 作者:行者123 更新时间:2023-11-30 23:25:21 25 4
gpt4 key购买 nike

我最近一直在阅读有关属性(即 property 装饰器)的内容,我得出的结论是我不太喜欢它在 python 中的实现方式。嗯,我知道它不是语言本身的内部部分(例如,它不像 C# 那样内置于语言中),但我真的认为他们可以更好地实现它(即使只使用装饰器)。我想对我认为应该实现的方式进行概念验证,但我遇到了一些障碍(不过没有什么是无法克服的......)。

这是我的想法:假设我们有一个 Person 类,具有属性 name。我定义属性的方式如下:

class Person():
def __init__(self, name, age):
self._name = name
self._age = age

@my_property
def name(self):
def getter(self):
return self._name

def setter(self, value):
self._name = value

def deleter(self):
del self._name

return getter, setter, deleter

我们的装饰器 my_property 定义如下:

def my_property(f):
d = {g.__name__: g for g in f(None)}
p = property(d.get('getter'), d.get('setter'), d.get('deleter'))
return p

现在,这很好用,但我真的很想通过允许用户不显式添加代码行来改进它:返回 getter、setter、deleter。相反,我希望装饰器将该行添加到传递给它的函数 f 中(在我们的例子中为 name 方法)。我想我必须使用 f 的代码对象(即 f.__code__),但我不知道如何实现我想要的。

我对属性的看法与属性的 C# 语法非常相似。我相信同一字段的 getter、setter 和删除器应该在某个代码块中分组在一起(在我的例子中,我选择了一个函数定义),而不是在(最多)3 个单独的方法中分布在整个类中(即使它们具有相同的名称,它们在语法上仍然是分开的)...此外,我认为它现在的定义方式 - 首先通过 property 装饰器将 getter 声明为属性,然后使用 getter 的名称来装饰 setter 和删除器,这非常难看。但这只是我:)

更新

接受@User的答案后,我使用他从包装器方法的代码对象内部获取代码对象的想法重新实现了我的属性装饰器。这是我的新实现,它仍然只是一个原型(prototype)(我相信它可以进一步改进)。我决定用我的新装饰器(它利用原始的 property 装饰器)隐藏内置 property 装饰器,但它可以被称为任何你想要的......总的来说,我认为这很酷,我希望 Python 有一个 property 关键字来定义属性,而不是使用方法定义或类定义(如 @User 中所建议的)他的回答)。

def property(f, property=property):
from types import CodeType, FunctionType
d = {code.co_name: FunctionType(code, f.__globals__)
for code in f.__code__.co_consts
if type(code) is CodeType}
return property(d.get('getter'), d.get('setter'), d.get('deleter'), f.__doc__)


class Person():
def __init__(self, name, age):
self._name = name
self._age = age

@property
def name():
def getter(self):
return self._name
def setter(self, value):
self._name = value
def deleter(self):
del self._name

>>> p1 = Person('Name', 25)
>>> p1.name
'Name'
>>> p1.name = "New Name"
>>> p1.name
'New Name'

最佳答案

现在你可以让它变得更漂亮:

>>> def dec(f):
import types
codes = []
for code in f.__code__.co_consts:
if isinstance(code, types.CodeType):
codes.append(code)
getter = types.FunctionType(codes[0], f.__globals__)
setter = types.FunctionType(codes[1], f.__globals__)
detter = types.FunctionType(codes[2], f.__globals__)
return property(getter, setter, detter, f.__doc__)

>>> class X:
@dec
def f():
def g(*args):
print('get', args)
def h(*args):
print('set', args)
def j(*args):
print('del', args)


>>> X().f
get (<__main__.X object at 0x02DFD870>,)
>>> X().f = 1
set (<__main__.X object at 0x02E13750>, 1)
>>> del X().f
del (<__main__.X object at 0x02DFD870>,)

我对你的想法很感兴趣。

但也许使用类装饰器会更好

@dec
class attribute:
# ... functions

或者也可能是 with 语句:

with makeProperty:
# ... functions

关于python - 如何向现有的 python 函数添加一行代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23044311/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com