python面向对象小tips
(一)、python鸭子类型
python作为动态语言继承和多态与静态语言(像java)有很大的不同;比如说在java中的某个方法,如果传入的参数是Animal
类型,那么传入的对象必须是Animal
类型或者其子类,否则,将无法调用run()
方法。对于Python来说,则不一定需要传入Animal
类型。我们只需要保证传入的对象有一个run()
方法就可以了,这就是动态语言中的“鸭子类型”,不强调严格的继承,只需要“看起来像鸭子就行了,即使你是一只天鹅”,
所以说你的对象只要有那个方法即可,这也是python面向过程或者说面向函数在对象中的体现所在!
# coding=utf-8 class Animal(object): def run(self): print('看,有只动物在跑') class Dog(Animal): def run(self): print('看,是只狗在跑') def eat(self): print('那狗在吃东西') class Car(object): def run(self): print('车启动了。。。') def gogogo(animal): animal.run() # animal.eat() gogogo(Dog()) print("--测试鸭子类型--") gogogo(Car())
(二)、python中的访问权限
1).在Python中,变量名以双下划线开头(__xxx__),并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,不要将对象的属性名弄成 '__xxx__' 这种格式;
2).以 '_xx'开头的实例变量是可以访问的,但是这只是告诉我们,它是可以被访问的,但是要看作私有变量,不要随意访问;
3).实例的变量名如果以'__xx'开头,这就成了一个私有变量(private),只有内部可以访问,“外部不能直接访问”,不能直接访问'__xx'是因为Python解释器对外把'__xx'变量改成了'_object__xx'
(这个很重要,可以帮助理解很多问题),所以,仍然可以通过'_object__xx'来访问'__xx'变量。
(三)、实例属性和类属性
# coding=utf-8
# python在创建实例的时候可以动态的绑定属性,给实例绑定属性,通过
dog = Dog()
dog.name = '二哈'
# 或者通过self变量来绑定,self永远代表所创建的实例本身 def __init__(self, name): self.name = name
# 如果要给Dog类本身绑定一个属性,则class
Dog(Animal):
name =
'er-ha'
属性虽然归类所有
,但类的所有实例都可以访问到,可以这么理解类的属性相当于给实例的属性添加个默认值而已
(四)、@property属性
通过python的@property装饰器,可以更深层次的理解scala中的getter和setter方法,被@property修饰的方法相当于getter,这个修饰器的好处就是不用直接暴露属性但是让使用者看起来“像是直接暴露了属性一样”
原来我们应该这样
#提供方法来设置和得到属性的值
class Car(object): def get_wheel(self): return self._wheel def set_wheel(self, name): if not isinstance(name, str): raise ValueError('wheel must be an str!') self._wheel = name
c = Car()
c.set_wheel = '三角'
print(c.get_wheel)
现在我们这样即可
class Car(object): @property def wheel(self): return self._wheel @score.setter def wheel(self, name): if not isinstance(name, str): raise ValueError('wheel must be an str!') self._wheel = name
c = Car()
c.wheel = '三角'
print(c.wheel)
(五)、python中的多重继承
这个特性与java中的interfac和scala中的trait有明显的不同,在python不管你是 is-a 还是 has-a 的关系,一律用class来实现;想给一个类扩展功能,直接继承拥有那个功能的类即可,python中叫“MixIn”(混入),跟scala中“混入”某个特质很相像,目的都是给一个类增加多个功能。
比如编写一个多线程的UDP服务:
class MinInUDPServer(UDPServer, ThreadingMixIn): pass
通过混入,这样就快速构造出我们需要的子类