python中的类接口
我越来越深入python,发现很难理解接口的概念 这个问题更具理论性 据我所知,为最终用户(非开发人员用户)提供接口是可取的,但是为什么类也应该为其他对象/类(基本上是其他程序/程序员)提供接口来使用呢?? 在本例中,在B类中使用注释1或注释2如何改变程序的功能python中的类接口,python,oop,Python,Oop,我越来越深入python,发现很难理解接口的概念 这个问题更具理论性 据我所知,为最终用户(非开发人员用户)提供接口是可取的,但是为什么类也应该为其他对象/类(基本上是其他程序/程序员)提供接口来使用呢?? 在本例中,在B类中使用注释1或注释2如何改变程序的功能 class A(): def __init__(self,a): self.a = a print self.a def seta(self,newa): #setter self.a =
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之前,我也试图理解不在程序中通过不同的对象修改属性的原因。使用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
属性设置为您想要的任何属性,直到尝试在get_char()
方法中使用pos
属性时,才会出现错误。这可能很难排除故障
因此,一些语言处理这一问题的一种方法是以某种方式屏蔽这些属性——可能通过将它们设置为“受保护”或“私有”——并通过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.set_pos(10)
和b.set_pos(“Foo”)
的调用都将导致索引器
,允许您立即捕获无效输入
输入Python的属性
但是Python给了我们(和装饰器)做同样的事情,但是更酷
考虑:
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类也与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的情况下更改内部表示形式,它们会很有用。接口的一个重要目的是鼓励松散耦合,其中一个类不依赖于其他类的内部实现。同时,它允许我们定义一个类,确信其他开发人员不会以可能导致意外行为的方式处理内部属性。它通过告诉其他开发人员“下面是您应该如何使用这个类”使事情变得更简单 在现实世界中,类的实现细节通常会发生很大的变化。如果其他类依赖于该类的内部实现细节,那么当这些细节发生更改时,依赖于该类的代码将开始出现故障。通过定义一个公共接口,一个类向依赖它的其他类承诺“我将始终拥有这些可用的属性和方法,即使我如何执行它们的细节可能会改变。” 此外,公共接口允许您定义更适合您工作领域的直观API。例如,考虑一个存储餐馆评论的程序。作为一个开发者,能够打电话给restaurant.average_review_score,而不必太多地谈论餐厅的定义,这会更好 关于这个想法的更多信息,我强烈推荐您阅读史蒂夫·麦康奈尔的《代码全集》
也就是说,在Python中,不使用getter或setter直接访问类的属性是很常见的。这与大多数其他OO语言(如java、C++和C语言)的约定有很大的不同。在这些语言中,语言本身包含用于区分公共接口和私有实现的结构。在Python中,我们依赖于约定和礼貌,尽可能不要与被标记为私有使用和下划线的成员混在一起。不要用Python编写getter和setter。在Python中不鼓励重复使用getter和setter。你凭什么认为这种用法是受鼓励的?@durga:什么书?如果有一本书告诉您在Python中使用getter和setter,请停止阅读它。我现在至少得到了一个上下文,其中这些方法是有用的。我现在会尽量把注意力集中在房产上。非常感谢。那解释有道理。。我会查一下你提到的那本书。
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())
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())