通过字符串变量在Python中设置和获取@property方法

问题描述 投票:6回答:2

目前我有一个通用函数,你可以传入一个属性名和一个类(它也适用于特定的对象实例,但我正在使用类),该函数将通过调用查找并操作该属性

getattr(model_class, model_attribute)

它将通过调用(此时在对象实例上)来修改属性

settattr(model_obj,key,value)

但是,我有一个类,我们定义了@property方法而不是简单属性,而setattr不起作用。如何基于该属性方法的字符串名称动态获取@property

也许我可以使用__dict__,但这看起来很脏而且不那么安全。

编辑:示例代码

广义函数

def process_general(mapping, map_keys, model_class, filter_fn, op_mode=op_modes.UPDATE):
    """
    Creates or updates a general table object based on a config dictionary.

    `mapping`: a configuration dictionary, specifying info about the table row value
    `map_keys`: keys in the mapping that we use for the ORM object
    `model_class`: the ORM model class we use the config data in
    `op_mode`: the kind of operation we want to perform (delete, update, add, etc.)

    Note that relationships between model objects must be defined and connected
    outside of this function.
    """
    # We construct a dictionary containing the values we need to set
    arg_dict = make_keyword_args(map_keys, mapping)

    # if we are updating, then we must first check if the item exists
    # already
    if (op_mode == op_modes.UPDATE):
        # Find all rows that match by the unique token.
        # It should only be one, but we will process all of them if it is the
        # case that we didn't stick to the uniqueness requirement.
        matches = filter_fn()

        # Keep track of the length of the iterator so we know if we need to add
        # a new row
        num_results = 0
        for match in matches:
            # and we set all of the object attributes based on the dictionary
            set_attrs_from_dict(match, arg_dict)
            model_obj = match
            num_results += 1
        # We have found no matches, so just add a new row
        if (num_results < 1):
            model_obj = model_class(**arg_dict)

        return model_obj

    # TODO add support for other modes. This here defaults to add
    else:
        return model_class(**arg_dict)

传入的示例类:

class Dataset(db.Model, UserContribMixin):
    # A list of filters for the dataset. It can be built into the dataset filter form dict
    # in get_filter_form. It's also useful for searching.
    filters     = db.relationship('DatasetFilter', backref='dataset')

    # private, and retrieved from the @property = select
    _fact_select = db.relationship('DatasetFactSelect', order_by='DatasetFactSelect.order')

    @property
    def fact_select(self):
        """
        FIXME: What is this used for?

        Appears to be a list of strings used to select (something) from the
        fact model in the star dataset interface.

        :return: List of strings used to select from the fact model
        :rtype: list
        """

        # these should be in proper order from the relationship order_by clause
        sels = [sel.fact_select for sel in self._fact_select]
        return sels
python attributes descriptor
2个回答
5
投票

调用getattr(model_class, model_attribute)将返回model_attribute引用的属性对象。我假设你已经知道这一点,并试图访问属性对象的值。

class A(object):

    def __init__(self):
        self._myprop = "Hello"

    @property
    def myprop(self):
        return self._myprop

    @myprop.setter
    def myprop(self, v):
        self._myprop = v

prop = getattr(A, "myprop")

print prop
# <property object at 0x7fe1b595a2b8>

现在我们已经从类中获取了属性对象,我们想要访问它的值。属性有三种方法fgetfsetfdel,它们提供了对该属性定义的gettersettterdeleter方法的访问。

由于myprop是一个实例方法,我们必须创建一个实例,以便我们可以调用它。

print prop.fget
# <function myprop at 0x7fe1b595d5f0>

print prop.fset
# <function myprop at 0x7fe1b595d668>

print prop.fdel  # We never defined a deleter method
# None

a = A()
print prop.fget(a)
#  Hello

1
投票

对于最一般的情况,请遵循以下示例:

class Foo(object):

    @property
    def bar(self):
        return self._spam

    @bar.setter
    def bar(self, v):
        self._spam = v

foo = Foo()
# prop = getattr(foo, "bar").fset('Aaaah')  # will raise an error
# if you wanna access the setter do:
getattr(type(foo), 'bar').fset(foo, 'Aaaah')
print(foo.bar)
© www.soinside.com 2019 - 2024. All rights reserved.