Pythonic别名为变量?

时间:2012-01-24 01:57:36

标签: python properties alias

我有一个类,我将数据存储在列表中以用于继承。我想知道,我已经完成了谷歌搜索的一部分,除了创建getter / setter函数和属性之外还有一个更清晰的方法来给这个列表中的元素赋一个别名吗?

例如......

class Serializable(object):
    """Adds serialization to from binary string"""

    def encode(self):
        """Pack into struct"""
        return self.encoder.pack(*self)

    def decode(self, data_str):
        """Unpack from struct"""
        self.data = self.encoder.unpack(data_str)
        return self.data


class Ping(Serializable):

    encoder = Struct("!16sBBBL")

    def __init__(self, ident=create_id(), ttl=TTL, hops=0, length=0):
        self.data = [ident, 1, ttl, hops, length]
        self.ident = property(self.data[0])

    def __getitem__(self, index):
        return self.data[index]

    @property
    def ident(self):
        return self.data[0]

    @ident.setter
    def ident(self, value):
        self.data[0] = value

    @property
    def protocol(self):
        return self.data[1]

    @protocol.setter
    def protocol(self, protocol):
        self.data[1]

我更倾向于使用更紧凑的解决方案来引用object.ident,同时保持上面打包和解压缩的能力。

3 个答案:

答案 0 :(得分:3)

如果您将值/属性存储在字典中:

def __init__(self, ident=create_id(), ttl=TTL, hops=0, length=0):
    self.data = {
        'ident': ident,
        'protocol': 1,
        'ttl': hops,
        'length': length,
    }

然后覆盖__getattr____setattr__

def __getattr__(self, attr):
    return self.data[attr]
def __setattr__(self, attr, value):
    if attr == 'data':
        object.__setattr__(self, attr, value)
    else:
        self.data[attr] = value

现在你可以这样做:

>>> ping = Ping()
>>> ping.protocol
1
>>> ping.protocol = 2
>>> ping.protocol
2

如果self.data绝对必须是一个列表,您可以改为:

class Ping(Serializable):

    mapping = ('ident', 'protocol', 'ttl', 'hops', 'length')

    encoder = Struct("!16sBBBL")

    def __init__(self, ident=create_id(), ttl=TTL, hops=0, length=0):
        self.data = [ident, 1, ttl, hops, length]

    def __getitem__(self, index):
        return self.data[index]

    def __getattr__(self, attr):
        index = self.mapping.index(attr)
        return self.data[index]

    def __setattr__(self, attr, value):
        if attr == 'data':
            object.__setattr__(self, attr, value)
        else:
            index = self.mapping.index(attr)
            self.data[index] = value

答案 1 :(得分:2)

def alias_property(key):
    return property(
        lambda self: getattr(self, key),
        lambda self, val: setattr(self, key, val),
        lambda self: delattr(self, key))

class A(object):

    def __init__(self, prop):
        self.prop = prop

    prop_alias = alias_property('prop')

答案 2 :(得分:0)

如果您的问题只是缩短了访问ident的代码,您可以在“旧样式”中使用“属性” - 也就是说,您传递给它,作为参数,getter和setter函数,而不是将它用作装饰器。

在这种情况下,函数非常小,它们可以是lambda函数,而不会影响代码的可读性。

class Ping(Serializable):

    encoder = Struct("!16sBBBL")

    def __init__(self, ident=None, ttl=TTL, hops=0, length=0):
        if ident is None:
            ident = create_id()
        self.data = [ident, 1, ttl, hops, length]
        # The line bellow looks like garbage -
        # it does not even make sense as a call to `property`
        # should have a callable as first parameter
        # returns an object that is designed to work as a class attribute
        # self.ident = property(self.data[0])
        # rather:
        self.ident = ident 
        # this will use the property defined bellow

    def __getitem__(self, index):
        return self.data[index]

    ident = property(lambda s: s.data[0], lambda s, v: s.data[0].__setitem__(0, v)
    protocol = property(lambda s: s.data[1], lambda s, v: s.data[1].__setitem__(1, v)