标签:简介 input 多态 __init__ port assm splay return 析构
Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。
在python中,一切皆对象。在学习python的面向对象程序设计之前,先来看看面向对象的基本特征。
1、面向对象特点:封装、继承、多态
2、面向对象程序设计思想:
先整体构想,规划多个对象,再由对象特性分别设计类
由类实例化不同的对象
由多个对象组合完成整个程序
3、python中的子类可以继承多个父类(一般就1-2个,python3新式类、经典类继承都是广度优先,python2中新式类采用广度优先,经典类采用深度优先)
4、封装,继承都是为了代码重用
5、多态:(一个接口,多重实现)接口重用 (注:python自身不支持多态,但可以用代码实现类似效果)
一、类的详解
1 例如: 2 class Role(object): 3 ac = None #类的变量,随着类的创建,存在与内存中 4 5 def __init__(self,name,role,weapon,life_value): 6 self.name = name 7 self.role = role #这都是成员变量(实例化的对象的变量) 8 self.weapon = weapon 9 self.life_value = life_value 10 11 def buy_weapon(self,weapon): 12 print(‘%s is buying [%s]‘ %(self.name,weapon)) 13 self.weapon = weapon 14 15 在这个类里面,有一个类的变量ac,可以理解为静态变量,要修改ac的值,需要通过‘ Role.ac = xxx ‘,即 类名.类变量名 16 17 类变量与成员变量区别: 18 1、类变量在定义类时就存在于内存中了,而成员变量只有在实例化时才被构造方法创造 19 2、定义时,成员变量前面都有self,而类变量没有。因为self时指向的不同对象,而类变量只 20 能由‘类名.类变量’来修改,可以通过‘对象.类变量’来访问,但是不能修改 21 22 类不能直接调用实例变量(实例变量存储在对象中,不在类中) 23 24 __init__() 是构造方法,在实例化对象时自动调用,就是用来初始化对象属性等 25 26 在实例化对象时,根据构造参数传递参数 27 28 定义类时,里面属性前面都有一个self,方法的第一个参数默认是self,这个self是指向实例化的对象,不是指向的类 29 30 31 内存详解: 32 在类定义时,就在系统内存里面生成了一块内存来存放类的内容,包括 类变量、类方法 等 33 即:类变量存储在类里面,类里面的方法也是存储在类这块内存里面的 34 35 构造函数是在实例化对象才会调用,所以构造函数里面的属性都是存在于实例化的对象的内存里面(是特定对象的属性) 36 37 对象调用类的方法: 38 在实例化对象时,并没有把类里面的方法都copy到对象内存空间里面,所以对象的内存空间里面只有属性,并没有方法 39 方法都是存在于类的内存中(这样就算是实例化了无数个对象,方法在内存中还是只有类空间里面这一份,节约空间) 40 方法都是类的方法,实例化对象在调用方法时,都会去类空间里面找。
类里面有共有属性和私有属性
1 ‘‘‘ 2 私有属性:只能在类里面通过类自己的方法调用,对象不能直接调用(可以通过方法) 3 要把一个属性变为私有属性,只需要在属性名前面加两个下划线‘__‘ 4 5 (特例,尽量别用)从外部直接访问私有变量方法: t._Human__life 6 7 ‘‘‘ 8 9 class Human(object): 10 __num = 10 11 def __init__(self,name): 12 self.name = name 13 self.__life = 100 14 15 def interface1(self): 16 print(‘血量 self.__life:‘,self.__life) 17 18 def interface2(self): 19 print(‘__num:‘,self.__num) 20 21 22 t = Human(‘Tom‘) 23 print(t.name) 24 #print(t.__life) 25 ‘‘‘ 26 builtins.AttributeError: ‘Human‘ object has no attribute ‘__life‘ 27 因为__life 是对象里面的私有属性,在外部不能直接调用,但可以通过方法调用 28 ‘‘‘ 29 t.interface1() #血量: 100 30 #print(Human.__num) 31 ‘‘‘ 32 builtins.AttributeError: type object ‘Human‘ has no attribute ‘__num‘ 33 ‘‘‘ 34 t.interface2() 35 36 print("特例访问私有变量方法 t._Human__life :",t._Human__life)
类里面不常用的特殊方法
1 #!/usr/bin/env python 2 #coding:utf-8 3 4 class A(object): 5 ‘‘‘Test class‘‘‘ 6 num = 10 7 8 #类里面的__init__()是由__new__()触发执行的 9 #def __new__(self): 10 #print("=======new======") 11 ‘‘‘ 12 =======new====== 13 None 14 报错:builtins.AttributeError: ‘NoneType‘ object has no attribute ‘__module__‘ 15 说明在这里重载__new__()方法后,没有再执行__init__() 16 ‘‘‘ 17 def __init__(self,name,age): 18 self.name = name 19 self.age = age 20 print(‘__init__‘) 21 22 def __call__(self): 23 print("__call__") 24 25 def test(self): 26 print("=====test=====") 27 #重载析构函数 28 def __del__(self): 29 print(‘deleting the ...‘) 30 31 a = A(‘root‘,20) 32 print(a.__doc__) 33 ‘‘‘ 34 Test class 35 __doc__ 获取类的说明(即:注释) 36 在定义类的函数时,最好在注释里面对其作用、功能、参数等做个说明 37 ‘‘‘ 38 ‘‘‘ 39 __module__ 表示当前操作的对象或类在那个模块 40 41 __class__ 表示当前操作的对象的类是什么 42 ‘‘‘ 43 print(a.__module__) 44 ‘‘‘ 45 __main__ 在这里代表的是当前模块。如果对象a在其他模块,则会打印a所在的模块名 46 ‘‘‘ 47 #import test.Human 48 from test import Human 49 #from test import h 50 h1 = Human() 51 #print(h.__module__) #test 52 print(h1.__module__) #test 53 print(h1.__class__) #<class ‘test.Human‘> 54 55 #python中,析构函数是: __del__() 析构函数会自己在程序执行结束自动调用 56 57 ‘‘‘ 58 __call__ 对象后面加括号,触发执行。 59 注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ; 60 而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()() 61 ‘‘‘ 62 #执行__call__ 方法 63 a() #__call__ 64 #A()() #__call__ 65 66 ‘‘‘ 67 __dict__ 只能显示对象中的所有成员变量,不能显示类变量 68 69 我们知道:实例变量(成员变量)属于对象;类中的静态变量和方法等属于类, 70 ‘‘‘ 71 print(a.__dict__) 72 ‘‘‘ 73 {‘name‘: ‘root‘, ‘age‘: 20} 74 ‘‘‘ 75 print(type(a)) #<class ‘__main__.A‘> 76 print(a) #<__main__.A object at 0x000001BA3967D128> 77 78 #类是由‘type‘创造出来的 79 print(type(A)) #<class ‘type‘>
类的方法
1 #!/usr/bin/env python 2 #coding:utf-8 3 4 ‘‘‘ 5 @classmethod 类方法装饰器(不能访问实例变量) 6 作用:把装饰的方法变为类方法(相似于类变量,只能通过类来访问,对象不能访问类方法) 7 8 @staticmethod 静态方法装饰器(不能访问类变量和实例变量) 9 作用:类的工具箱,与类直接相互独立,要调用类的东西只有传参(一般不用) 10 11 @property 类属性装饰器 12 作用:把装饰的方法变为一个属性(能调用,不可执行) 13 14 ‘‘‘ 15 class Animal(object): 16 hobbie = "meat" 17 def __init__(self,name): 18 self.name = name 19 self.num = None 20 21 @classmethod #类方法,不能访问实例变量 22 def talk(self): 23 print(‘%s is talking...‘ %self.hobbie) #可以直接调用,但不能修改 24 #print(‘%s is talking...‘ %self.name) 25 ‘‘‘ 26 builtins.AttributeError: type object ‘Animal‘ has no 27 attribute ‘name‘ 28 ‘‘‘ 29 30 @staticmethod 31 def walk(self): 32 print(‘%s is walking...‘ %self.name) 33 ‘‘‘ 34 builtins.TypeError: walk() missing 1 required positional 35 argument: ‘self‘ 36 不知道self是谁,在调用时应该把self当参数传进来 37 ‘‘‘ 38 39 @property 40 def habit(self): 41 print("%s habit is xxoo" %self.name) 42 ‘‘‘ 43 builtins.TypeError: ‘NoneType‘ object is not callable 44 ‘‘‘ 45 46 #property 用法补充 47 #1、直接调用(此时不能传值,否则报错) 48 @property 49 def total_player(self): 50 print("this is a property") 51 return self.num 52 53 #2、经过1后,total_player变成了属性,因此可以用setter 54 @total_player.setter 55 def total_player(self,num): 56 self.num = num 57 print("self.num:",self.num) 58 59 #3、相对于2可以给属性传值,那么也可以用删除属性值 60 @total_player.deleter 61 def total_player(self): 62 print("total player got deleted") 63 del self.num 64 65 d = Animal(‘zhaolin‘) 66 d.talk() 67 d.walk(d) 68 d.habit 69 #1: 70 d.total_player 71 #2: 72 d.total_player = 20 73 #3: 74 del d.total_player #用deleter时,要这样调用 75 76 ‘‘‘ 77 meat is talking... 78 zhaolin is walking... 79 zhaolin habit is xxoo 80 81 this is a property 82 self.num: 20 83 total player got deleted 84 85 ‘‘‘
二、类的使用
继承:由一般(很多类都具有的共性)到特殊(不同的类有不同的特性)
子类继承父类时,构造方法需要 【先重写,再继承】
1 #!/usr/bin/env python 2 #coding:utf-8 3 4 ‘‘‘ 5 继承:由一般(很多类都具有的共性)到特殊(不同的类有不同的特性) 6 7 子类继承父类时,构造方法需要 【先重写,再继承】 8 ‘‘‘ 9 10 class SchoolMember(object): 11 def __init__(self,name,age,sex): 12 self.name = name 13 self.age = age 14 self.sex = sex 15 self.enroll() 16 17 def enroll(self): 18 print(‘[%s] was enrolled!‘ %self.name) 19 20 def tell(self): 21 print(‘[%s] is telling!‘ %self.name) 22 23 class Teacher(SchoolMember): 24 def __init__(self, name, age, sex,course,salary): #先重写 25 super(Teacher,self).__init__(name,age,sex) #再继承 26 self.course = course 27 self.salary = salary 28 29 def teaching(self): 30 print(‘Teacher [%s] is teaching [%s]‘ %(self.name,self.course)) 31 32 def get_salary(self): 33 print(‘Teacher [%s] is saving salary [%s]‘ %(self.name,self.salary)) 34 35 class Student(SchoolMember): 36 student_nums = 0 37 def __init__(self, name, age, sex,course,tuition): #先重写 38 super(Student,self).__init__(name,age,sex) #再继承 39 self.course = course 40 self.tuition = tuition 41 Student.student_nums += 1 42 43 def enroll(self): 44 #super(Student,self).enroll() #在子类里面重写enroll(),不继承 45 print(‘The [%s] student [%s] is enrolled!‘ %(self.student_nums,self.name)) 46 #这里可以用self.student_nums,是因为只是访问student_nums,而没有修改它 47 48 def studying(self): 49 print(‘Student [%s] is studying!‘ %self.name) 50 51 def pay_tuition(self): 52 print(‘The tuition of Student [%s] is [%s]‘ %(self.name,self.tuition)) 53 54 #实例化对象 55 t1 = Teacher(‘txowner‘, 22, ‘male‘, ‘python‘, 3000) 56 t2 = Teacher(‘xtsec‘, 24, ‘male‘, ‘php‘, 2500) 57 ‘‘‘ 58 实例化对象的过程: 59 eg:t2 = Teacher(‘xtsec‘, 24, ‘male‘, ‘php‘, 2500) 60 1、t2 = Teacher() 在内存中开辟一块内存,让t2指向该内存 61 2、Teacher(t2) 把t2这块内存与类Teacher相关联(这也是为什么self是指向对象的而不是类) 62 3、把各个参数传递给类的构造方法,在对象t2空间里面创建各个成员变量 63 64 ‘‘‘ 65 66 s1 = Student(‘root‘, 20, ‘male‘, ‘python‘, 15000) 67 s2 = Student(‘lucy‘, 18, ‘female‘, ‘php‘, 12000) 68 69 t1.teaching() 70 t2.teaching() 71 s1.studying() 72 s2.studying() 73 print(‘t1老师的salary:‘,t1.salary) 74 print(‘s2同学的tuition:‘,s2.tuition)
1 #!/usr/bin/env python 2 #coding:utf-8 3 4 ‘‘‘先实验老式类(经典类)的写法‘‘‘ 5 6 #class A(object): #新式类 7 class A: #经典类 8 def f2(self): 9 print(‘f2 from A‘) 10 11 class B(A): 12 def f1(self): 13 print(‘f1 from B‘) 14 15 def f2(self): 16 print(‘f2 from B‘) 17 18 class C(A): 19 def f2(self): 20 print(‘f2 from C‘) 21 22 class D(B,C): 23 pass 24 25 d = D() 26 d.f1() 27 d.f2() 28 ‘‘‘ 29 f1 from B 30 f2 from B 31 32 由以上结果可知:在多继承时,若多个父类都有相同方法或属性,则按照广度优先方式继承 33 即:继承父类的方法时,若都有相同方法名的方法,则按照继承时的顺序从左至右继承一个 34 ‘‘‘ 35 ‘‘‘ 36 在python2.x版本: 37 38 深度优先:同一条线上优先,比如上面如果按照深度优先的话,D在调用f2时,先去找 39 父类B,如果B里 40 面没有f2,那么D就会去调用A里面的f2,而不会调用C里面的f2,老式类就是这样 41 42 广度优先:同一水平层次优先,比如上面如果按照广度优先的话,D在调用f2时,先去找 43 父类B,如果B里面没有f2,那么D就会去调用C里面的f2,而不会调用A里面的f2,新式类就是 44 这样 45 46 在python3.x版本: 47 不管是新式类还是经典类,在继承时,都采用广度优先 48 ‘‘‘
python实现多态调用
1 #!/usr/bin/env python 2 #coding:utf-8 3 4 ‘‘‘ 5 python没有多态。多态是java、c#、c++这类强类型语言特有的 6 7 python可以利用函数等方式来实现多态现象。 8 9 ‘‘‘ 10 class Animal(object): 11 def __init__(self): 12 print(‘Animal Class‘) 13 14 def talk(self): 15 pass 16 17 class Dog(Animal): 18 def __init__(self): 19 print(‘Dog Class‘) 20 21 def talk(self): 22 return (‘woof!woof!‘) 23 24 class Cat(Animal): 25 def __init__(self): 26 print(‘Cat Class‘) 27 28 def talk(self): 29 return (‘muaao~‘) 30 31 dog = Dog() 32 cat = Cat() 33 dog.talk() 34 cat.talk() 35 36 #利用函数实现统一接口 37 def animal_talk(obj): 38 print(obj.talk()) 39 40 animal_talk(dog) 41 print(‘=====‘) 42 animal_talk(cat)
三、反射的妙用
1 #!/usr/bin/env python 2 #coding:utf-8 3 4 ‘‘‘ 5 反射是非常非常重要的! 6 反射的作用:通过一个字符串来去调用一个对象中名字跟字符串值相同的方法(属性)的内存地址 7 ‘‘‘ 8 9 import sys 10 11 class WebServer(object): 12 def __init__(self,host,port): 13 self.host = host 14 self.port = port 15 16 def start(self): 17 print("Server is starting...") 18 def stop(self): 19 print("Server is stoped...") 20 def restart(self): 21 self.stop() 22 self.start() 23 24 def test_run(ins,name): 25 print("test_run",name,ins.host) 26 27 28 if __name__ == ‘__main__‘: 29 #print(sys.argv[0],sys.argv[1]) 30 ‘‘‘ 31 sys.argv是一个获取文件名后面参数的数组,sys.argv[0]是当前文件路径, 32 后面依次为传递的参数 33 ‘‘‘ 34 server = WebServer(‘localhost‘, 8080) 35 if hasattr(server, sys.argv[1]): 36 #if hasattr(WebServer, sys.argv[1]): #对象或类名都可以 37 func = getattr(server,sys.argv[1]) #得到对象server中名字与传入字符串相等的函数(方法) 38 func() 39 else: 40 print("your input incorrect!") 41 42 #server1 = WebServer(‘localhost1‘, 80) 43 #setattr(server1,‘run‘,test_run) 44 #server1.run(server1,‘admin‘) 45 46 #delattr(server1,‘port‘) 47 #print(server1.port) 48 #AttributeError: ‘WebServer‘ object has no attribute ‘port‘ 49 50 ‘‘‘ 51 以下的obj可以是类,也可以是实例化的对象 52 53 hasattr(obj,attr) 判断对象中有没有指定属性(方法) 54 55 getattr(obj,attr) 获取对象中的属性(方法)的内存地址 56 57 setattr(obj,attr,method) 把方法(属性)method添加到对象中,并改名为attr 58 通过对象调用method:obj.attr 59 60 这样把方法(属性)添加到对象中与原生方法区别: 61 不会自动把self传进去,若要调用obj原生属性,只有先把obj当成参数传进去 62 63 delattr(obj,attr) 把对象obj里面的attr属性(方法)删除掉 64 注意:因为实例化对象的方法是存在于类中,对象只是能访问类中的方法,不能 65 更改,但是对象可以更改自己的成员变量。所以这里的attr是对象自身的属性 66 或方法,不是类里面的。 67 68 可以通过delattr(classname,attr)来删除类的属性(方法) 69 70 ‘‘‘ 71 ‘‘‘ 72 #方式比较low 73 cmd_dict = { 74 ‘start‘:server.start, 75 ‘stop‘:server.stop, 76 ‘restart‘:server.restart 77 } 78 if sys.argv[1] in cmd_dict: 79 cmd_dict[sys.argv[1]]() 80 else: 81 print("your input incorrect!") 82 83 ‘‘‘ 84
标签:简介 input 多态 __init__ port assm splay return 析构
原文地址:http://www.cnblogs.com/xtsec/p/6963638.html