面向对象编程:一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
1、类(class)
- class:自定义的对象数据类型。基于类创建多个对象,每个对象具备类的通用行为,首字母大写(面向对象的设计思想是抽象出Class,根据Class创建Instance【实例】)
__init__
方法:第一个参数self
表示创建的实例本身,在内部把各种属性绑定到self
,因为self
指向创建的实例本身。可把一些必要的属性先填进去,如:姓名、年龄等
1 #创建一个类,假设为人 2 class Person(object): 3 #使用__init__方法初始化创建的实例属性 4 def __init__(self,name,age,gender): 5 self.name = name 6 self.age = age 7 self.gender = gender 8 #定义创建的实例所拥有的技能 9 def eat(self): 10 print('%s,You have the skills to eat' %self.name) 11 def motion(self): 12 print('%s,%s,is a %s'%(self.name,self.age,self.gender)) 13 14 #创建实例 15 j = Person('jack',18,'boy') 16 l = Person('lisa',18,'girl') 17 #使用技能 18 j.eat() 19 l.motion() 20 21 输出: 22 jack,You have the skills to eat 23 lisa,18,is a girl
- 数据封装:类本身所拥有的数据,在内部使用函数封装起来,称为类的方法。(如下文的print_name与get_name两个函数)
- 访问限制:在方法前用双下划线:__xx 表示默认数据不被外部重新修改
1 class Person(object): 2 def __init__(self,name,age): 3 self.__name = name 4 self.__age = age 5 def print_name(self): 6 print('%s %s'%(self.__name,self.__age)) 7 #使用新函数为外部需要获取私有参数,外部无法直接使用self.name调用数据 8 def get_name(self): 9 return self.__name 10 jack = Person('jack',19) 11 print(jack.print_name()) 12 print(jack.get_name()) 13 14 输出: 15 jack 19 16 None 17 jack
- 继承:可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写。
1 #Dog类继承Animal类,可使用其内部方法 2 class Animal(object): 3 def run(self): 4 print('Animal is running') 5 class Dog(Animal): 6 pass
测试对象属性:
hasattr(Person,'x'):判断Person对象是否有‘x’属性;
setattr(Person,'y',18):设置一个属性‘y’以及对应的值;
getattr(Person,'y',404):获取属性‘y’的值,如属性不存在时可设置返回值,不然会得到AttributeError的错误。
- 类属性:直接在class中定义的属性,归类所有。所有实例共享一个属性;
- 实例属性:属于各个实例所创建的属性,互不干扰(实例属性和类属性不使用相同的名字,相同时实例属性会屏蔽类属性)。
1 class Animal(object): 2 class_name = 'dog' #类属性 3 def __init__(self,name): 4 self.name = name 5 c = Animal('cat') #实例属性 6 print(c.name) 7 print(c.class_name) 8 9 输出: 10 cat 11 dog
- super():是用于调用父类(超类)的一个方法
1 class People(object): 2 def print(self): 3 print('父类方法') 4 class Man(People): 5 def print(self): 6 print('子类方法') 7 s = Man() 8 s.print() 9 super(Man,s).print() 10 11 输出: 12 子类方法 13 父类方法
- __slots__:定义一个特殊的变量,来限制该class实例能添加的属性
1 class People(object): 2 __slots__ = ('name','age') 3 s = People() #创建新的实例 4 s.name = 'jcak' #绑定属性 5 s.age = 18 6 #s.score = 90 #再添加属性时得到AttributeError的错误
- @property装饰器:把一个方法变成属性调用的。单个getter为可读,再定义.setter属性为可读写。
1 #用@property给一个Screen对象加上width和height属性,以及一个只读属性resolution 2 class Screen(object): 3 @property 4 def width(self): 5 return self._width 6 @width.setter 7 def width(self,input_width): 8 self._width = input_width 9 @property 10 def height(self): 11 return self._height 12 @height.setter 13 def height(self,input_height): 14 self._height = input_height 15 @property 16 def resolution(self): 17 return self._width*self.height 18 s = Screen() 19 s.width = 1024 20 s.height = 768 21 print('resolution =', s.resolution) 22 if s.resolution == 786432: 23 print('测试通过!') 24 else: 25 print('测试失败!') 26 27 输出: 28 resolution = 786432 29 测试通过!
- 定制类:形如
__xxx__
的变量或者函数名来定制类- __str__、__call__、__dco__、__dict__、__class__
1 class Student(object): 2 '''描述类信息''' 3 def __init__(self, name): 4 self.name = name 5 6 def __str__(self): 7 return 'Student Object (name:%s)' % self.name 8 9 def __call__(self, *args, **kwargs): 10 return '实例对象s +()直接运行' 11 12 s = Student('jack') 13 print(s) #默认输出_str__中返回的内容 14 print(s.__doc__) #输出描述类信息 15 print(s.__module__) #当前操作对象所在的模块 16 print(s.__class__) #当前操作对象的类 17 print(s()) #对实例直接调用,返回call的内容 18 # print(Student.__dict__) #以字典形式返回当前类中所有对应的关系 19 print(s.__dict__) 20 21 输出: 22 Student Object (name:jack) 23 描述类信息 24 __main__ 25 <class '__main__.Student'> 26 实例对象s +()直接运行 27 {'name': 'jack'}
- __iter__
1 class Cycle(): 2 def __init__(self): 3 self.a,self.b = 0,1 4 def __iter__(self): #返回一个迭代对象 5 return self 6 def __next__(self): #获取下一个值 7 self.a,self.b = self.a+self.b,self.b 8 if self.a > 4: 9 raise StopIteration 10 return self.a 11 12 for n in Cycle(): 13 print(n) 14 15 输出: 16 1 17 2 18 3 19 4
- __getitem__、__setitem__(设置)、__delitem__(删除)
1 class Cycle(): 2 def __getitem__(self, i): #返回索引 3 a,b = 1,1 4 for x in range(i): 5 a,b = a+b,b 6 return a 7 8 print(Cycle()[3]) 9 class Cycle(): #q求切片 10 def __getitem__(self,n): 11 start = n.start 12 stop = n.stop 13 l = [] 14 a,b =1,1 15 for x in range(stop): 16 if x >= start: 17 l.append(a) 18 a,b = b,a+b 19 return l 20 print(Cycle()[1:4]) 21 22 输出: 23 3 24 [1, 2, 3]
- __str__、__call__、__dco__、__dict__、__class__
-
- __getattr__:当调用的属性不存在时,会从getattr获取属性,并返回值,要让class只响应特定的几个 属性,我们就要按照约定,抛出
AttributeError
的错误1 语法: 2 getattr(object, name[, default]) 3 4 object -- 对象 5 name -- 字符串,对象属性。 6 default -- 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError。
1 class Student(object): 2 3 def __getattr__(self, attr): 4 if attr=='age': 5 return lambda: 25 6 raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)
- __setattr__:设置属性值,该属性必须存在
1 语法:setattr(object,name,value) 对象;对象属性;属性值。 2 3 class Num(): 4 foo = 1 5 a = Num() 6 print(getattr(a,'foo')) #获取属性的值 7 setattr(a,'foo',8) #设置属性的值 8 print(a.foo) 9 10 输出: 11 1 12 8
- __getattr__:当调用的属性不存在时,会从getattr获取属性,并返回值,要让class只响应特定的几个 属性,我们就要按照约定,抛出
- 枚举类
1 #@unique装饰器可以帮助检查保证没有重复值 2 from enum import Enum, unique 3 @unique 4 class Weekday(Enum): 5 Sun = 0 # Sun的value被设定为0 6 Mon = 1 7 8 day = Weekday.Mon 9 print(day.value) #使用value的值或得枚举常量 10 #----*---- 11 12 Month = Enum('Month', ('Jan', 'Feb')) 13 for name, member in Month.__members__.items(): 14 print(name, '=>', member, ',', member.value) 15 print(Month.Jan.value) 16 17 输出: 18 1 19 #----*---- 20 Jan => Month.Jan , 1 21 Feb => Month.Feb , 2 22 1
- type():可用来创建一个class对象,需传入的三个参数
- class的名称
- 继承的父类集合,注意Python支持多重继承,如果只有一个父类,使用tuple的单元素写法(后加逗号)
- class的方法名称与函数绑定,这里我们把函数
fn
绑定到方法名hello
上1 def fn(self,name = 'World'): 2 print('Hello,%s' %name) 3 H = type('Hello',(object,),dict(hello = fn)) # H 最好与 Hello 写一样防止混淆 4 # class Hello(object): 5 # def hello(self, name='world'): 6 # print('Hello, %s.' % name) 7 h = H() 8 h.hello() 9 print(type(H)) 10 print(H.__name__) 11 12 输出: 13 Hello,World 14 <class 'type'> 15 Hello
- Metaclass:元类,metaclass允许创建类或者修改类,类相当于metaclass创建的实例(内容较复杂,先行省略!!!)
- __name__ 与 __main__:python的文件有两种使用的方法,一是直接作为脚本执行,二是import到其他的python脚本中被调用(模块重用)执行。if __name__ == 'main': 的作用就是控制这两种情况执行代码的过程,在if __name__ == '__main__': 下的代码只有在第一种情况下(即文件作为脚本直接执行)才被执行,而import到其他脚本中是不会被执行的。每个python模块都包含内置的变量__name__,当运行模块被执行的时候,__name__等于文件名(包含了后缀.py);如果import到其他模块中,则__name__等于模块名称(不包含后缀.py)。而“__main__”等于当前执行文件的名称(包含了后缀.py)。