如何借助元类将 python 方法转换为 setter?
How to turn python method into setter with the help of metaclass?
我是 metaclasses 的新手,所以很抱歉,如果我的问题有点愚蠢。我需要制作一个 metaclass,它采用 class 的特定方法并将它们转换为 属性 方法或设置器。所以,如果我有
class TestClass():
def __init__(self, x: int):
self._x = x
def get_x(self):
print("this is property")
return self._x
def set_x(self, x: int):
print("this is setter")
self._x = x
我希望它像这样工作:
class TestClass():
def __init__(self, x: int):
self._x = x
@property
def x(self):
print("this is property")
return self._x
@x.setter
def x(self, x: int):
print("this is setter")
self._x = x
现在我刚刚知道如何为 属性:
class PropertyConvert(type):
def __new__(cls, future_class_name, future_class_parents, future_class_attr):
new_attr = {}
for name, val in future_class_attr.items():
if not name.startswith('__'):
if name.startswith('get_'):
new_attr[name[4:]] = property(val)
if name.startswith('set_'):
# ???
else:
new_attr[name] = val
return type.__new__(cls, future_class_name, future_class_parents, new_attr)
但我不知道如何为二传手做这件事。
我强烈推荐docs about descriptors,它们写得很好,解释了很多类似的例子。
但是回答你的问题,要使 setter 工作,你需要使用相同的 property 函数但填写第二个参数。
class property(fget=None, fset=None, fdel=None, doc=None)
因此代码可能如下所示:
class PropertyConvert(type):
def __new__(cls, future_class_name, future_class_parents, future_class_attr):
new_attr = {}
fget, fset, property_name = None, None, None
for name, val in future_class_attr.items():
if not name.startswith("__"):
if name.startswith("get_"):
property_name = name[4:]
fget = val
if name.startswith("set_"):
property_name = name[4:]
fset = val
else:
new_attr[name] = val
if n:
new_attr[property_name] = property(fget, fset)
return type.__new__(cls, future_class_name, future_class_parents, new_attr)
我是 metaclasses 的新手,所以很抱歉,如果我的问题有点愚蠢。我需要制作一个 metaclass,它采用 class 的特定方法并将它们转换为 属性 方法或设置器。所以,如果我有
class TestClass():
def __init__(self, x: int):
self._x = x
def get_x(self):
print("this is property")
return self._x
def set_x(self, x: int):
print("this is setter")
self._x = x
我希望它像这样工作:
class TestClass():
def __init__(self, x: int):
self._x = x
@property
def x(self):
print("this is property")
return self._x
@x.setter
def x(self, x: int):
print("this is setter")
self._x = x
现在我刚刚知道如何为 属性:
class PropertyConvert(type):
def __new__(cls, future_class_name, future_class_parents, future_class_attr):
new_attr = {}
for name, val in future_class_attr.items():
if not name.startswith('__'):
if name.startswith('get_'):
new_attr[name[4:]] = property(val)
if name.startswith('set_'):
# ???
else:
new_attr[name] = val
return type.__new__(cls, future_class_name, future_class_parents, new_attr)
但我不知道如何为二传手做这件事。
我强烈推荐docs about descriptors,它们写得很好,解释了很多类似的例子。
但是回答你的问题,要使 setter 工作,你需要使用相同的 property 函数但填写第二个参数。
class property(fget=None, fset=None, fdel=None, doc=None)
因此代码可能如下所示:
class PropertyConvert(type):
def __new__(cls, future_class_name, future_class_parents, future_class_attr):
new_attr = {}
fget, fset, property_name = None, None, None
for name, val in future_class_attr.items():
if not name.startswith("__"):
if name.startswith("get_"):
property_name = name[4:]
fget = val
if name.startswith("set_"):
property_name = name[4:]
fset = val
else:
new_attr[name] = val
if n:
new_attr[property_name] = property(fget, fset)
return type.__new__(cls, future_class_name, future_class_parents, new_attr)