关于python:同一属性的2个名称

2 names for a same attribute

我想知道是否有一种方法可以"链接"一个类的两个属性,或者将两个名称赋予同一个属性?

例如,我正在编写一个脚本,它根据用户提供的数据创建三角形。我的三角形是ABC。三角形的边是ab、bc和ca。因此三角形有三个属性(self.ab、self.bc、self.ca)。但是ab=ba,所以我想允许用户使用print myInstance.BA,而不是print myInstance.AB

所以我想创建属性self.ab和属性ba(返回self.ab)。当我试着用print myInstance.BA而不是print myInstance.AB的时候,这很管用,但是我很贪婪…

我还希望允许用户使用myInstance.BA = 5而不是myInstance.AB = 5,这样做时还可以编辑属性ab。

有办法吗?


python属性可以有setter。所以你只需要

1
2
3
4
5
6
7
8
9
class Foo(object):

  @property
  def BA(self):
      return self.AB

  @BA.setter
  def BA(self, value):
      self.AB = value

并由@amccormack的答案inspred,如果您可以依赖属性名的顺序,则这更一般地适用于边缘BC、CD:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  class Foo(object):


      def __init__(self):
          self.ab = 100

      def __getattr__(self, name):
          return getattr(self,"".join(sorted(name)))

      def __setattr__(self, name, value):
          super(Foo, self).__setattr__("".join(sorted(name)), value)


  f = Foo()

  print f.ba
  f.ba = 200
  print f.ba


实现这一点的一种方法是将您的边存储在字典的自定义实现中,如本so答案中所述。

这种技术的好处是,在编写代码时,您不必知道边的名称是什么。

我们所做的是更改哈希查找函数,以便在字典查找键之前,对键进行排序。因为键被排序,所以ba变为ab等。排序发生在SideDict类内的__keytransform__函数中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import collections


class TransformedDict(collections.MutableMapping):
   """A dictionary that applies an arbitrary key-altering
       function before accessing the keys"""


    def __init__(self, *args, **kwargs):
        self.store = dict()
        self.update(dict(*args, **kwargs))  # use the free update to set keys

    def __getitem__(self, key):
        return self.store[self.__keytransform__(key)]

    def __setitem__(self, key, value):
        self.store[self.__keytransform__(key)] = value

    def __delitem__(self, key):
        del self.store[self.__keytransform__(key)]

    def __iter__(self):
        return iter(self.store)

    def __len__(self):
        return len(self.store)

    def __keytransform__(self, key):
        return key

class SideDict(TransformedDict):

    def __keytransform__(self, key):
        return ''.join(sorted(key))

side=SideDict()
print 'assign 3 to abc'
side['abc']=3
print"side['abc']", side['abc']
print 'assign 5 to abc'
side['bac']=5
print"side['abc']", side['abc']
print"side['bca']", side['bca']

运行此代码会产生:

1
2
3
4
5
assign 3 to abc
side['abc'] 3
assign 5 to abc
side['abc'] 5
side['bca'] 5