我是新手,我发现在编写类时,我必须不断地编写

@property
def example(self):
    return self._example

@example.setter
def example(self, example):
     if #some conditions here:
          self._example = example

我正在做一个项目,其中有十几个这样的项目,所以我试图做一个函数,它将接受一个属性名和一些条件,并为它做一个getter,setter和deleter.

class Util:

    @classmethod
    def custom_property(cls, prop, conds=None, deletable=False):
        def getter(self):
            return getattr(self, f'_{prop}')

        def setter(self, value):
            if conds is None or conds(value):
                setattr(self, f'_{prop}', value)
            else:
                raise ValueError(f'Invalid value for {prop}')

        def deleter(self):
            if deletable:
                del self._value
            else:
                print("This attribute can't be deleted.")

        # setattr(target, prop, property(getter, setter, deleter))

        return [getter, setter, deleter]

下面是我try 使用它的一个例子:

from utils import Util

def name_conds(name):
    if not isinstance(name, str):
        raise TypeError("City name must be a string")
    if not name.strip():
        raise ValueError("City name cannot be blank")
    if not 2 <= len(name) <= 25:
        raise ValueError("City name length must be between 2 and 25 characters")
    return True

class City:

    def __init__(self, name):
        self._name = name

    [name_getter, name_setter, name_deleter] = Util.custom_property("name", name_conds)
    name = property(name_getter, name_setter, name_deleter)

不幸的是,这并不完全有效.如果我创建一个名称为"asdf"的城市并try 将其更改为"a",我会得到正确的错误,即长度错误,但如果我使用名称"a"实例化一个新城市,我可以毫不费力地这样做.人们肯定有某种方式像我一样把属性写出来?此外,正如Util中的注释行所示,我希望能够通过在任何需要属性的类中调用Util.Custom_Property来更快地使用该方法,但这会将该属性添加到Util中(当然,因为它会将其添加到CLS中).似乎无法在City内将类City作为参数,但在City外调用Customer_Property可能意味着City中的函数无法正确引用名称.

推荐答案

问题不在于你的财产,而在于你不是using的财产._name实际上是属性本身的私有实现细节(尽管值存储在City的实例上),所以City方法也不应该直接使用它.


在回答这个问题时,我会指出custom_property不必是一个类方法(或任何类的方法);它可以是一个普通函数.此外,它可以返回property实例本身,您可以将其直接分配给City的属性.最后,您可以通过定义一个参数来优化setter,如果condsNone,则无条件设置值;如果deletableFalse,则只需省略删除符.

def custom_property(cls, prop, conds=None, deletable=False):
    name = f'_{prop}'

    def getter(self):
        return getattr(self, name)

    if conds is None:
        def setter(self, value):
            setattr(self, name, value)
    else:
        def setter(self, value):
            if conds(value):
                setattr(self, name, value)
            else:
                raise ValueError(f'Invalid value for {prop}')

    if deletable:
        def deleter(self):
            delattr(self, name)
    else:
        deleter = None

    return property(getter, setter, deleter)

然后

from utils import custom_property


def name_conds(name):
    if not isinstance(name, str):
        raise TypeError("City name must be a string")
    if not name.strip():
        raise ValueError("City name cannot be blank")
    if not 2 <= len(name) <= 25:
        raise ValueError("City name length must be between 2 and 25 characters")
    return True


class City:

    def __init__(self, name):
        self.name = name  # Use the property, not _name

    name = custom_property("name", name_conds)

Python相关问答推荐

如何从具有多个嵌入选项卡的网页中Web抓取td类元素

如何在虚拟Python环境中运行Python程序?

Python中绕y轴曲线的旋转

avxspan与pandas period_range

Pandas计数符合某些条件的特定列的数量

连接一个rabrame和另一个1d rabrame不是问题,但当使用[...]'运算符会产生不同的结果

不允许访问非IPM文件夹

如何从需要点击/切换的网页中提取表格?

使用Python查找、替换和调整PDF中的图像'

Geopandas未返回正确的缓冲区(单位:米)

matplotlib图中的复杂箭头形状

如何防止Pandas将索引标为周期?

为什么常规操作不以其就地对应操作为基础?

OpenGL仅渲染第二个三角形,第一个三角形不可见

pysnmp—lextudio使用next()和getCmd()生成器导致TypeError:tuple对象不是迭代器''

使用Python异步地持久跟踪用户输入

如果有2个或3个,则从pandas列中删除空格

如何将返回引用的函数与pybind11绑定?

在matplotlib中重叠极 map 以创建径向龙卷风图

对包含JSON列的DataFrame进行分组