Python学习之面向对象编程
面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
类和实例
定义
class Student(object): pass stone = Student() stone.name = "stone" stone.age = 2 print(stone.name, stone.age)
上面代码中:
- class后面紧接的是类名,类名以大写字母开头
- (object)是该类从哪个类继承下来的
- 使用时候可以*的给实例变量绑定属性
方法
class Student(object): def __init__(self, name, age): self.name = name self.age = age def print_info(self): print(self.name, self.age) stone = Student("stone", 18) stone.print_info()
上面代码中:
-
__init__
方法的第一个参数永远是self
,表示创建的实例本身,因此,在__init__
方法内部,就可以把各种属性绑定到self
,因为self
就指向创建的实例本身。类似于java的构造函数。 - 定义一个方法,除了第一个参数是
self
外,其他和普通函数一样。要调用一个方法,只需要在实例变量上直接调用,除了self
不用传递,其他参数正常传入。
访问限制
__ __xxx__
继承和多态
在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。和java一样。
静态语言 vs 动态语言:
对于静态语言(例如Java)来说,如果需要传入 Animal
类型,则传入的对象必须是 Animal
类型或者它的子类,否则,将无法调用 Animal
中的方法。对于Python这样的动态语言来说,则不一定需要传入 Animal
类型。我们只需要保证传入的对象有 Animal
中的方法就可以了。
对象信息
使用type()
>>> import types >>> def fn(): ... pass ... >>> type(fn)==types.FunctionType True >>> type(abs)==types.BuiltinFunctionType True >>> type(lambda x: x)==types.LambdaType True >>> type((x for x in range(10)))==types.GeneratorType True
以上代码可以看出,判断基本数据类型可以直接写 int
, str
等,但如果要判断一个对象是否是函数怎么办?可以使用 types
模块中定义的常量。
使用isinstance()
>>> isinstance([1, 2, 3], (list, tuple)) True >>> isinstance((1, 2, 3), (list, tuple)) Tru
可以判断一个变量是否是某些类型中的一种,比如上面的代码就可以判断是否是list或者tuple
使用dir()
如果要获得一个对象的所有属性和方法,可以使用 dir()
函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:
>>> dir('ABC') ['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']
类似 __xxx__
的属性和方法在Python中都是有特殊用途的,比如 __len__
方法返回长度。在Python中,如果你调用 len()
函数试图获取一个对象的长度,实际上,在 len()
函数内部,它自动去调用该对象的 __len__()
方法,所以,下面的代码是等价的:
>>> len('ABC') 3 >>> 'ABC'.__len__() 3
我们自己写的类,如果也想用 len(myObj)
的话,就自己写一个 __len__()
方法:
>>> class MyDog(object): ... def __len__(self): ... return 100 ... >>> dog = MyDog() >>> len(dog) 100
仅仅把属性和方法列出来是不够的,配合 getattr()
、 setattr()
以及 hasattr()
,我们可以直接操作一个对象的状态:
>>> class MyObject(object): ... def __init__(self): ... self.x = 9 ... def power(self): ... return self.x * self.x ... >>> obj = MyObject()
紧接着,可以测试该对象的属性:
>>> hasattr(obj, 'x') # 有属性'x'吗? True >>> obj.x 9 >>> hasattr(obj, 'y') # 有属性'y'吗? False >>> setattr(obj, 'y', 19) # 设置一个属性'y' >>> hasattr(obj, 'y') # 有属性'y'吗? True >>> getattr(obj, 'y') # 获取属性'y' 19 >>> obj.y # 获取属性'y' 19
也可以获得对象的方法:
>>> hasattr(obj, 'power') # 有属性'power'吗? True >>> getattr(obj, 'power') # 获取属性'power' <bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>> >>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn >>> fn # fn指向obj.power <bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>> >>> fn() # 调用fn()与调用obj.power()是一样的 81
实例属性和类属性
类本身需要绑定一个属性:
class Student(object): name = 'Student'
当我们定义了一个类属性后,这个属性虽然归类所有,但类的所有实例都可以访问到。来测试一下:
>>> class Student(object): ... name = 'Student' ... >>> s = Student() # 创建实例s >>> print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性 Student >>> print(Student.name) # 打印类的name属性 Student >>> s.name = 'Michael' # 给实例绑定name属性 >>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性 Michael >>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问 Student >>> del s.name # 如果删除实例的name属性 >>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了 Student
python学习交流群:125240963
下一篇: MyBatis动态sql