Python中的有用继承或接口的替代方案
你好,按照我所了解的,在Python中,变量是没有类型的。所以我想要创建一个基类
class baseClass:
def x():
print "yay"
以及两个子类
class sub1(baseClass):
def x():
print "sub1"
class sub2(baseClass):
def x():
print "sub2"
在其他编程语言中,我可以根据接口来开发,就像这样
baseClass c = new sub1()
这样我就可以使用c作为基类,并且拥有sub1的功能,也许在运行时我可以通过
c = new sub2()
来改变它。这在Python中也可以吗?
3 个回答
Python其实没有“变量”。它有的是名字,这些名字和一些对象是绑定在一起的。
class X(object):
pass
class Y(object):
pass
class Z(object):
pass
a = X # name "a" bound with class object "X"
print(a is X) # prints True
a = Y
print(a is Y) # prints True
b = Y
print(a is b) # prints True
上面的代码展示了如何把名字“a”先绑定到一个对象(定义为“X”的类对象),然后再绑定到另一个对象(类对象“Y”)。接着,我们把“b”绑定到类对象“Y”。这样一来,“a”和“b”就指向了同一个对象,所以用is
来测试时会返回True
。
Python是强类型的。只要“a”绑定的是类对象“Y”,那么“a”的类型就是这个类对象的类型。例如,如果你在数学表达式中使用“a”,Python会抛出一个TypeError
异常,因为“a”的类型不对。
print(a + 3) # causes TypeError exception
不过,把一个名字重新绑定到其他对象上是始终合法的,这样新的对象可以有不同的类型。
a = 3
print(a + 3) # prints 6
这里有个很好的解释:http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#python-has-names
是的,你可以这样做;不过,创建对象的语法不是“new Class(args)”。你只需要去掉“new”。
先退一步,假设你有一个变量叫做foo,里面存着一个对象。编译器不会对你做以下操作提出任何问题:
foo.bar
即使foo根本不可能有一个叫bar的属性,编译器也不会抱怨。这是因为foo是否有一个名为bar的属性是在运行时决定的(这就是为什么Python是一种动态类型语言)。如果你的代码有类型问题,你可能要等到真正运行它的时候才会发现(也就是运行时)。
在Python中,接口完全是由同一个项目的开发者之间的约定来建立的。这种处理接口的方法被称为鸭子类型。我建议你了解一下这个主题,因为看起来你对Python还不太熟悉。
附言:动态类型听起来可能不太好,因为你得不到编译时的类型检查,但另一方面,你需要写的样板代码会少很多。从理论上讲,这会让你更高效。根据我的经验,这种情况通常是成立的。
是的。
c = sub1()
c = sub2()
但是,基类和定义接口的概念在这里并不必要,因为Python不是静态类型的语言。
补充:
要把你的代码改写成有效的Python代码:
# This space where baseClass was defined intentionally left blank,
# because it serves no purpose
class Sub1(object):
def x(self):
print "sub1"
class Sub2(object):
def x(self):
print "sub2"
c = Sub1()
c = Sub2()