python自动上课_Python自动化开发课堂笔记【Day07】 - Python进阶(类)- 02

本文详细讲解了Python中的类与对象概念,包括类的定义、实例化、属性引用,以及类方法、静态方法和绑定方法的使用。通过实例展示了类的继承、多态性,并探讨了封装的意义和实现。文章最后提到了Python的反射机制及其应用。
摘要由CSDN通过智能技术生成

类与对象

对象是特征(变量)与技能(函数)的结合体,类是一系列对象共有的特征与技能的结合体

现实生活中:先有对象,再总结归纳出类

程序中:一定是先定义类,再实例化出对象

定义类的语法:

class 类名:

'''注释'''

类体(可以是任意代码)

1 classChinese:2 country = 'China'

3 def __init__(self,name,age):4 self.name =name5 self.age =age6 print('--->',self.name,self.age)7 deftalk(self):8 print('say Chinese')

1. 类的第一种用法,实例化

1 p1 = Chinese('Albert',18)2 p2 = Chinese('Baker',33)

2. 类的第二种用法,属性引用

1 print(Chinese.country)#类的数据属性

2 print(Chinese.__init__)#类的函数属性

3 p1.__init__('Talbert',81)

3. 其他知识点补充

1 print(Chinese.__dict__)#查看类的属性字典,或者说是名称空间

2 #{'__module__': '__main__', '__doc__': None, 'talk': , '__weakref__': , 'country': 'China', '__dict__': , '__init__': }

3 print(Chinese.country)4 print(Chinese.__dict__['country'])#效果同上,本质上是如何取到的country这个变量

5 print(p1.name,p1.age)6 print(p1.__dict__['name'],p1.__dict__['age'])7

8 #类型和类是统一的

9 print(type(p1)) #

10

11 #类中定义的变量对象是公用的,不会产生新的内存空间

12 print(id(p1.country)) #5593664

13 print(id(p2.country)) #5593664

14 print(id(Chinese.country)) #5593664

类绑定方法(类实例化后绑定到对象身上)

绑定方法:绑定到谁身上就是给谁用的,谁来调用就会自动把自己当作第一个参数传入

1 print(Chinese.talk) #

2 print(p1.talk) #>

3 print(p2.talk) #>

总结:定义在类内部的变量是所有对象共有的,id全一样。定义在类内部的函数,是绑定到所有对象的,是给对象来用的,obj.func()会把obj本身当作第一个参数传入

print(p1.x) # p1.__dict__ ---> Chinese.__dict__ ---> 报错

如果要查找一个属性,先从对象名称空间中查找,找不到之后再到类名称空间查找,如果还找不到不会再去全局找,直接报错

练习:

1 1.统计类实例化对象的次数2 classChinese:3 country = 'China'

4 count =05 def __init__(self,name,age):6 self.name =name7 self.age =age8 Chinese.count += 1 #类变量的概念

9 print('--->',self.name,self.age)10 print('%d obj create' %Chinese.count)11 p1=Chinese('A',1)12 p2=Chinese('B',2)13

14 2.定义一个学生类15 classStu:16 def __init__(self,stuid,name,age):17 self.stuid =stuid18 self.name =name19 self.age =age20 print('Student--->',self.stuid,self.name,self.age)21 s1 = Stu(1,'A',18)22 s2 = Stu(2,'B',18)23

24 3.类对象交互25 classA:26 camp = 'AAA'

27 def __init__(self,nickname,damage=100, HP=200):28 self.nickname =nickname29 self.damage =damage30 self.HP =HP31 defattack(self,enemy):32 enemy.HP -=self.damage33 print('造成%d点伤害' %self.damage)34 classB:35 camp = 'BBB'

36 def __init__(self,nickname,damage=200, HP=100):37 self.nickname =nickname38 self.damage =damage39 self.HP =HP40 defattack(self,enemy):41 enemy.HP -=self.damage42 print('造成%d点伤害' %self.damage)43 a1 = A('a1')44 b1 = B('b1')45 print(a1.camp)46 print(b1.camp)47 a1.attack(b1)48 b1.attack(a1)

继承

继承是一种创建新类的方式,新建的类可以继承一个或多个父类,父类又可以称为基类或超类,新建的类称为派生类或子类

1 classParentClass1:2 pass

3 classParentClass2:4 pass

5 classSubClass1(ParentClass1):6 pass

7 classSubClass2(ParentClass1,ParentClass2):8 pass

如何查看继承的父类

1 print(SubClass1.__bases__) #(,)

2 print(SubClass2.__bases__) #(, )

类的种类

1 #Python2中分为新式类和经典类

2 #新式类(有括号的,有继承关系的)

3 classFoo(object):4 pass

5 #经典类(没括号的,谁都不继承)

6 classBar:7 pass

8 #Python3中全部都是经典类(即使没有括号也是新式类)

9 classFoo:10 pass

11 print(Foo.__bases__) #(,)

继承的好处:

1.减少冗余代码

2.在子类定义新的属性,覆盖掉父类的属性,称为派生

1 classAnimal:2 def __init__(self,name,age,sex):3 self.name =name4 self.age =age5 self.sex =sex6 defeat(self):7 print('eating...')8 deftalk(self):9 print('%s saying...' %self.name)10 classPeople(Animal):11 def __init__(self,name,age,sex,edu):12 Animal.__init__(self,name,age,sex)13 self.edu =edu14 deftalk(self):15 Animal.talk(self)16 print('%s say hello' %self.name)17 classPig(Animal):18 pass

19 classDog(Animal):20 pass

21 p1 = People('p1',18,'male','college')22 g1 = Pig('g1',11,'female')23 d1 = Dog('d1',22,'male')24 print(p1.edu)25 p1.talk()26 g1.talk()27 d1.talk()28 print(isinstance(p1,People))29 print(isinstance(g1,Pig))30 print(isinstance(d1,Dog))

对象如果要调用方法,先从对象自己的命名空间找,然后是自己的类,最后是父类,依次往上找

1 classParent:2 deffoo(self):3 print('Parent.foo')4 self.bar()5 defbar(self):6 print('Parent.bar')7 classSub(Parent):8 defbar(self):9 print('Sub.bar')10 s=Sub()11 s.foo() #Parent.foo

12 #Sub.bar

继承反应的是一种什么是什么的关系

组合也可以解决代码冗余的问题,但是组合反应的是一种什么有什么的关系

1 classPeople:2 def __init__(self,name,age,sex):3 self.name=name4 self.age=age5 self.sex=sex6 classDate:7 def __init__(self,y,m,d):8 self.y =y9 self.m =m10 self.d =d11 deftell(self):12 print('%s-%s-%s' %(self.y,self.m,self.d))13 classTeacher(People):14 def __init__(self,name,age,sex,salary,y,m,d):15 People.__init__(self,name,age,sex)16 self.salary =salary17 self.birth =Date(y,m,d)18

19 classStudent(People):20 def __init__(self,name,age,sex,y,m,d):21 People.__init__(self,name,age,sex)22 self.birth =Date(y,m,d)23

24 t1 = Teacher('A',18,'male',3000,2000,1,1)25 t1.birth.tell()

抽象类

1 importabc2 class File(metaclass=abc.ABCMeta):3 @abc.abstractmethod4 defread(self):5 pass

6 @abc.abstractmethod7 defwrite(self):8 pass

9 classTxt(File):10 defread(self):11 pass

12 defwrite(self):13 pass

14 p=Txt()

继承搜索顺序:

Python2中,分为

广度优先(新式类)F->D->B->A->E->C->H

深度优先(经典类)F->D->B->E->C->H->A

Python3中,只有广度优先(python3中只有新式类)

1 classA:2 def test(self): print('from A')3 pass

4 classB(A):5 def test(self): print('from B')6 pass

7 classC(A):8 def test(self): print('from C')9 pass

10 classD(B):11 def test(self): print('from D')12 pass

13 classE(C):14 def test(self): print('from E')15 pass

16 classH(A):17 def test(self): print('from H')18 pass

19 classF(D,E,H):20 def test(self): print('from F')21 pass

22 f=F()23 f.test()24 print(F.mro())25 #[, , , ,

26 #, , , ]

子类中重用父类的方法(super)

1 classFoo:2 deftest(self):3 print('from foo.test')4 classBar(Foo):5 deftest(self):6 super().test()7 print('from bar.test')8 b =Bar()9 b.test()10

11 classFoo1:12 deftest(self):13 print('from foo1.test')14 classFoo2:15 deftest(self):16 print('from foo2.test')17 classBar(Foo1,Foo2):18 deftest(self):19 super().test()20 print('from bar.test')21 b =Bar()22 b.test() #from foo1.test

23 #from bar.test

多态与多态性

没有多态就没有多态性

多态:同一种事物的多种形态

多态性:指的是具有不同功能的函数可以使用相同的函数名

1 classAnimal:2 defeat(self):3 print('eating...')4 classPeople(Animal):5 defeat(self):6 print('eating...')7 classPig(Animal):8 defeat(self):9 print('eating...')10 classDog(Animal):11 defeat(self):12 print('eating...')13 p1=People()14 g1=Pig()15 d1=Dog()16 deffunc(obj):17 obj.eat()18 func(p1)19 func(g1)20 func(d1)

封装

为什么要封装:保护隐私,隔离复杂度

Python没有真正的隐藏,只是从语法级别做了些改变

1 classFoo:2 __x = 1 #'_Foo__x': 1

3 def __test(self): #'_Foo__test':

4 print('from test')5 print(Foo.__dict__)6 print(Foo._Foo__x)7 print(Foo._Foo__test)8

9 classPeople:10 __country = 'Chinese'

11 def __init__(self,name,age,sex):12 self.__name=name #只在定义阶段才会发生变形,实例产生后新加入的变量就不会变形了

13 self.__age=age14 self.__sex=age15 deftell_info(self):16 print('%s:%s:%s' % (self.__name,self.__age,self.__sex))17 p=People('alex',18,'male')18 print(p.__dict__) #{'_People__age': 18, '_People__sex': 18, '_People__name': 'alex'}

19 p.tell_info()20 p.__salary = 3000

21 print(p.__dict__) #{'_People__name': 'alex', '_People__sex': 18, '_People__age': 18, '__salary': 3000}

22

23 classPeople:24 __country = 'Chinese'

25 def __init__(self,name,age):26 self.__name=name27 self.__age=age28 deftell_info(self):29 print('Name:%s,Age:%d' % (self.__name,self.__age))30 defset_info(self,x,y):31 if notisinstance(x,str):32 raise TypeError('must be str!!!')33 if notisinstance(y,int):34 raise TypeError('must be int!!!')35 self.__name =x36 self.__age =y37 p1 = People('Albert',18)38 p1.tell_info() #Name:Albert,Age:18

39 p1.set_info('Baker',22)40 p1.tell_info() #Name:Baker,Age:22

关于property的应用

1 应用1:2 classFoo:3 @property4 deftest(self):5 print('from foo')6 #test = property(test)

7 f=Foo()8 #f.test() #from foo

9 f.test #from foo

10

11 应用2:12 classPeople:13 def __init__(self,name,weight,height):14 self.name =name15 self.weight =weight16 self.height =height17 @property18 defbmi(self):19 return self.weight / (self.height ** 2)20 p = People('Albert',75,1.80)21 p.height=1.82

22 print(p.bmi)23

24 应用3:25 importmath26 classCircle:27 def __init__(self,radius):28 self.raduis =radius29 @property30 defzc(self):31 return 2 * math.pi *self.raduis32 c = Circle(5)33 print(c.zc)34

35 应用4:36 classPerson:37 def __init__(self,name,permission=False):38 self.__name =name39 self.permission =permission40 @property41 defname(self):42 return self.__name

43 @name.setter44 defname(self,value):45 if notisinstance(value,str):46 raise TypeError('must be str')47 self.__name =value48 @name.deleter49 defname(self):50 if notself.permission:51 raise PermissionError('not allowed')52 del self.__name

53 p=Person('Albert')54 print(p.name)55 p.name='Baker'

56 print(p.name)57 p.permission =True58 del p.name

绑定

类中定义的函数分成两大类:

1.绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入)

1.绑定到类的方法:用classmethod装饰器装饰的方法。

为类量身定制

类.bound_method(),自动将类当作第一个参数传入(其实对象也可调用,但仍将类当作第一个参数传入)

2.绑定到对象的方法:没有被任何装饰器装饰的方法。

为对象量身定制

对象.bound_method(),自动将对象当作第一个参数传入(属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值的说法)

2.非绑定方法:用staticmethod装饰器装饰的方法

不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说,就是一个普通工具而已

1 #绑定到类的方法

2 classFoo:3 @classmethod4 deftest(cls):5 print(cls)6 Foo.test() #

7 #跟谁都不绑定的方法

8 classFoo:9 @staticmethod10 deftest(x,y):11 print('test',x,y)12 Foo.test(1,3)13 f=Foo()14 f.test(2,4)

示例

1 #setting文件配置

2 #HOST = '127.0.0.1'

3 #PORT = 3306

4 importsetting5 importhashlib6 importtime7 classMySQL:8 def __init__(self,host,port):9 self.sql_id =self.sql_id()10 self.host =host11 self.port =port12 print('connecting...')13 @classmethod14 deffrom_conf(cls):15 return cls(setting.HOST,setting.PORT) #相当于MySQL(host,port)

16 @staticmethod17 defsql_id():18 m = hashlib.md5(str(time.clock()).encode('utf-8'))19 returnm.hexdigest()20 defselect(self):21 print(self) #<__main__.mysql object at>

22 print('select func',self.host,self.port)23

24 conn1 = MySQL('192.168.1.1',3306)25 conn1.select()26 print(conn1.sql_id)27 conn2 =MySQL.from_conf()28 print(conn2.sql_id)

staticmeth与classmethod的区别

1 classPerson:2 def __init__(self,name,age):3 self.name =name4 self.age =age5 def __str__(self):6 print('run __str__')7 return 'name:%s age:%s' %(self.name, self.age)8 p = Person('Albert',19)9 print(p)10

11 #setting文件配置

12 #HOST = '127.0.0.1'

13 #PORT = 3306

14 importsetting15 classMySQL:16 def __init__(self,host,port):17 self.host =host18 self.port =port19 print('connecting...')20 @classmethod21 deffrom_conf(cls):22 returncls(setting.HOST, setting.PORT)23 def __str__(self):24 return 'from MySQL'

25 classMariadb(MySQL):26 def __str__(self):27 print(self.host,self.port)28 return 'from Maria'

29 conn1 =Mariadb.from_conf()30 print(conn1)

反射(自省)

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问,检测和修改它本身状态或行为的一种能力。

Python面向对象中的反射:通过字符串的形式操作对象相关的属性。Python中的一切皆对象(都可以使用反射)

1 classPeople:2 country = 'China'

3 def __init__(self,name,age):4 self.name=name5 self.age=age6 print(People.country)7 p = People('Albert',18)8 print(p)9 print(hasattr(p,'name')) #True

10 print(hasattr(People,'country')) #True

11 setattr(p,'sex','male')12 print(p.__dict__) #{'age': 18, 'name': 'Albert', 'sex': 'male'}

13 print(getattr(p,'nam','not exist')) #not exist

14 print(getattr(p,'name'))15 #setattr(p,'x',1)

16 if hasattr(p,'x'):17 res = getattr(p,'x')18 print(res)19 delattr(p,'sex')20 print(p.__dict__)

练习

1 importsys2 res = sys.modules[__name__] #获取当前模块

3 print(res)4 if hasattr(res,'People'):5 get = getattr(res,'People')6 print(get)7 obj=get('Baker',22)8 print(obj.name)9

10

11 classFTPClient:12 def __init__(self,host):13 self.host=host14 print('connecting...%s' %self.host)15 definteractive(self):16 whileTrue:17 cmd_line = input('>>>:').strip()18 cmd_list =cmd_line.split()19 ifhasattr(self,cmd_list[0]):20 func =getattr(self,cmd_list[0])21 func(cmd_list)22 defget(self,args):23 print('downloading...%s' % args[1])24 p = FTPClient('127.0.0.1')25 p.interactive()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值