python中的类接口 - python

我将自己更多地投入到python中,并发现很难理解接口的概念。

这个问题更具理论性。

据我了解,为最终用户(非开发者用户)提供接口是可取的,但是为什么类也应该具有供其他对象/类(基本上是其他程序/程序员)使用的接口呢?
在示例中,如何在B类中使用comment1或comment 2更改程序的功能?

class A():
   def __init__(self,a):
      self.a = a
      print self.a
   def seta(self,newa): #setter
      self.a = newa
      print self.a
   def geta(self): #getter
      return self.a


class B(object):
   def __init__(self,oobj,b):
      self.b = b
      self.oobj = oobj
      print self.b
   def addab(self):
      #a = self.oobj.geta() # —> 1. using interface : the getter method 
      #return (self.b +a)
      return (self.b+self.oobj.a) # —> 2.directly accessing the a attribute

希望我已经清楚了..

编辑:
我确实检查了提到的其他可能重复的线程,但是即使在尝试了解@property之前,我仍在尝试了解不要在程序中由不同对象自己修改属性的背后原理。

python大神给出的解决方案

使用setter方法的原因之一是立即验证输入,而不是让无效值传播到代码中。越早识别无效值,就越容易进行故障排除。

考虑以下类别:

class A():
    def __init__(self, s, pos):
        self.s   = s
        self.pos = pos

    def get_char(self):
        return self.s[self.pos]

现在考虑以下代码:

a = A("Foo", 1)
a.pos = 2 
a.pos = 10              # Raises no error... yet
a.pos = "Foo"           # Raises no error... yet
# ... time passes ...
print(a.get_char())     # Raises an error now, but much later than when an invalid attribute was set

您可以将pos属性设置为所需的值,直到尝试在pos方法中使用get_char()属性时,错误才会出现。这可能很难进行故障排除。

因此,某些语言处理此问题的一种方法是以某种方式屏蔽这些属性(可能是通过使它们成为“受保护的”或“私有的”),并让其他代码通过getter和setter访问它们。

这样,可以将代码添加到setter方法中,然后验证该值。

例如:

class B():
    def __init__(self, s, pos):
        self._s   = s
        self._pos = pos

    def get_pos(self):
        return self._pos

    def set_pos(self, newpos):
        if not 0 < newpos < len(self._s): raise IndexError
        self._pos = newpos

    def get_char(self):
        return self._s[self._pos]

b = B("Foo", 1)
b.set_pos(2)            # This is fine
b.set_pos(10)           # This raises an error
b.set_pos("Foo")        # This raises an error
# ... time passes ...
print(b.get_char())

现在,对b.set_pos(10)b.set_pos("Foo")的调用都将产生一个IndexError,使您可以立即捕获无效的输入。

输入Python的属性

但是Python为我们提供了properties(和@property装饰器),它们执行相同的操作,但效果更好。

考虑:

class C(object):
    def __init__(self, s, pos):
        self._s   = s
        self._pos = pos

    @property
    def pos(self):
        return self._pos

    @pos.setter
    def pos(self, newpos):
        if not 0 < newpos < len(self._s): raise IndexError
        self._pos = newpos

    def get_char(self):
        return self._s[self._pos]

C类执行与B类完全相同的输入验证。

c = C("Foo", 1)
c.pos = 2               # This is fine
c.pos = 10              # This raises an error
c.pos = "Foo"           # This raises an error
# ... time passes ...
print(c.get_char())

但是,通过属性,C类也看起来与A类完全一样!

与类A和C交互的两部分代码可供参考:

a = A("Foo", 1)
a.pos = 2
a.pos = 10
a.pos = "Foo"
print(a.get_char())

c = C("Foo", 1)
c.pos = 2
c.pos = 10
c.pos = "Foo"
print(c.get_char())

从A类开始并不少见,然后当需要某种输入验证时,以C类结束。

因此,有了属性,您就可以安全地获得getter / setter方法的灵活性,而无需更改外部代码。

注意:输入验证不是需要getter / setter方法的唯一原因。例如,如果您想(有条件地)修改给定值或更改内部表示而又不影响API,它们将非常有用。