Python 3学习 ——面向对象
Posted jinzejun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 3学习 ——面向对象相关的知识,希望对你有一定的参考价值。
Python 学习——面向对象
写此博客 是为了激励自己,并且将自己的心得以及遇到的问题与人分享
一、面向对象基础
面向对象就是一个类和对象的应用。
1.定义方法:
----------------------------------------------------------------
class 类名:
def 方法名(self , arg):
print(arg)
中间人 = 类名()
中间人.方法名(arg)
----------------------------------------------------------------
self 代指,调用方法的 对象 (中间人)
2.构造方法:类名加()自动执行构造方法
1 class Person: 2 def __init__(self,name,age): 3 self.n = name 4 self.a = age 5 def show(self): 6 print("%s %s " %(self.n,self.a)) 7 8 liufeiduo = Person(‘刘飞铎‘,19) 9 liufeiduo.show() 10 11 chengjunfei = Person(‘程俊飞‘,18) 12 chengjunfei.show()
3.继承
1 class Father: # 父类,基类 2 def 篮球(self): 3 pass 4 def 足球(self): 5 pass 6 def 抽烟(self): 7 pass 8 9 class Son(Father): # 子类,派生类 10 def 排球(self): 11 pass 12 13 14 s = Son() 15 s.篮球()
子类重写父类方法
1 class F: 2 def f1(self): 3 print(‘F,f1‘) 4 def f2(self): 5 print(‘F,f2‘) 6 7 class S(F): 8 def s1(self): 9 print(‘S,s1‘) 10 def f2(self): 11 print(‘S,s2‘) 12 13 obj = S() 14 obj.s1() #S,s1 s1中的self 是形参,此时代指 obj 15 obj.f2() #S,s2
self 永远指调用方法的调用者
两种调用父类的方法:
方法一: super
class F: def f1(self): print(‘F,f1‘) def f2(self): print(‘F,f2‘) class S(F): def s1(self): print(‘S,s1‘) def f2(self): super(S,self).f2() #执行父类中的f2方法 #super代指了它的父类 print(‘S,s2‘) obj = S() obj.f2() ‘‘‘ F,f2 S,s2 ‘‘‘
方法二:通过父类名调用方法
class F: def f1(self): print(‘F,f1‘) def f2(self): print(‘F,f2‘) class S(F): def s1(self): print(‘S,s1‘) def f2(self): #super(S,self).f2() #执行父类中的f2方法 #super代指了它的父类 print(‘S,s2‘) F.f2(self) obj = S() obj.f2() ‘‘‘ S,s2 F,f2 ‘‘‘
多继承:Python 与 C++ 独有支持多继承,一个子类可以继承多个父类。
1 class F1: 2 def a(self): 3 print(‘F1.a‘) 4 5 class F2: 6 def a(self): 7 print(‘F2.a‘) 8 9 class Son(F1,F2): # 按照从左到右的顺序,"一条路找到黑的顺序"来进行找。 如果有同一个根时,根最后执行。 10 pass 11 12 obj = Son() 13 obj.a() #F1.a
4.多态
1 def func(arg): 2 print(arg) 3 # Python 中的原生多态,不被类型所限定。 4 func(1) 5 6 func(‘llalala‘)
二、面向对象中级
1.类成员
字段
普通字段,保存在对象中,执行只能通过对象访问。
静态字段,保存在类中,在内存中只保存一份,执行时可以通过对象访问也可以通过类进行访问。
1 class Provience: 2 country = ‘中国‘ 3 4 def __init__(self,name): 5 self.name = name 6 henan = Provience(‘河南‘) 7 print(Provience.country) #中国 8 print(henan.name) #河南
方法
普通方法,保存在类中,由对象来进行调用。self --> 对象
静态方法,保存在类中,由类直接调用。
类方法,保存在类中,由类直接调用。cls --> 当前类
1 class Foo: 2 3 def bar(self): #普通方法 4 print(‘bar‘) 5 6 @staticmethod 7 def sta(a1,a2): #静态方法 self 就不是必须存在的了 8 print(a1,a2) 9 10 @classmethod 11 def classmd(cls): #类方法 cls 是类名 不依赖对象 可以通过类直接执行 12 print(cls) 13 print(‘classmd‘) 14 15 object = Foo() 16 object.bar() #bar 17 18 Foo.sta(2,4) #2 4 调用者直接类调用就可以了 19 20 Foo.classmd() # <class ‘__main__.Foo‘> classmd
应用场景:
如果对象中需要保存一些值,执行某功能时,需要使用对象中的值 ---> 普通方法。
不需要任何对象中的值 ---> 静态方法。
类的成员——属性:按照方法的方式写,按照字段调用的方式调用。
1 class Foo: 2 def __init__(self): 3 self.name = ‘a‘ 4 5 def bar(self): 6 print(‘bar‘) 7 8 @property #通过property装饰器 9 def per(self): # 属性: 伪造成方法,但访问的时候使用的是字段的方式 10 print(‘per‘) 11 12 obj = Foo() 13 obj.per
利用 属性 完成分页的功能:
class Pergination: def __init__(self,current_page): self.page = int(current_page) @property def start(self): val = (self.page - 1) * 10 return val @property def end(self): val = self.page * 10 return val li = [] for i in range(1000): li.append(i) while True: p = input(‘请输入要查看的页码: ‘)# 每页显示十条 obj = Pergination(p) print(li[obj.start:obj.end])
三、面向对象高级
1. 成员修饰符
公有成员
私有成员 __字段名
- 无法直接访问,只能间接访问
- 继承过来的私有字段是无法进行访问,内部访问指的是自身内部,继承过来的不可以。
私有字段
1 class Foo: 2 3 def __init__(self,name,age): 4 self.name = name 5 # self.age = age 6 self.__age = age # 私有,外部无法直接进行访问 7 8 def show(self): #间接访问私有字段方法 9 return self.__age 10 11 obj = Foo(‘chengjunfei‘,20) 12 print(obj.name) 13 print(obj.show()) #间接访问私有字段
2. 特殊成员
__init__ 类() 自动执行
__call__ 对象() 类()()自动执行
1 class Foo: 2 3 def __init__(self): 4 print(‘init‘) 5 6 def __call__(self,*args,**kwargs): 7 print(‘call‘) 8 9 10 11 Foo()() #init call 12 13 object = Foo() 14 object() #对象后面加括号会执行 __call__ 中的方法,Python的一个内置语法。
__int__ int(对象)
__str__ str(对象)
__add__
1 class Foo: 2 def __init__(self): 3 pass 4 5 def __add__(self, other): 6 return 123 7 8 obj1 = Foo() 9 obj2 = Foo() 10 11 r = obj1 + obj2 12 # 两个对象相加时,自动执行第一个对象的__add__方法,并且将第二个对象当作参数传递进去。 13 14 print(r,type(r)) #123 <class ‘int‘>
__del__ 析构方法,当对象被销毁时,自动执行。
__dict__ 将对象中封装的所有内容通过字典的形式返回。
1 class Foo: 2 3 def __init__(self,name,age): 4 self.name = name 5 self.age = age 6 7 object = Foo(‘刘飞铎‘,21) 8 9 d = object.__dict__ 10 print(d) #{‘name‘: ‘刘飞铎‘, ‘age‘: 21} 11 12 c = Foo.__dict__ 13 print(c) #{‘__module__‘: ‘__main__‘, ‘__init__‘: <function Foo.__init__ at 0x0000016D6A1499D8>, 14 # ‘__dict__‘: <attribute ‘__dict__‘ of ‘Foo‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Foo‘ objects>, 15 # ‘__doc__‘: None}
__getitem__ # 切片(slice类型)或者索引 有返回值
__setitem__ 没有返回值
__delitem__ 没有返回值
1 class Foo: 2 3 def __init__(self,name,age): 4 self.name = name 5 self.age = age 6 7 def __getitem__(self, item): 8 return item + 10 9 10 def __setitem__(self, key, value): 11 print(key) 12 print(value) 13 14 def __delitem__(self, key): 15 print(key) 16 17 18 li = Foo(‘Liufeiduo‘,22) 19 r = li[8] #自动执行li对象中的__getitem__方法,8当作参数传递给了item 20 21 print(r) #18 22 23 li[100] = ‘asdf‘ # def __setitem__(self, key, value): 24 del li[985] # def __delitem__(self, key):
__iter__ :如果类中有 __iter__ 方法,对象 ---> 可迭代对象。
对象.__iter__ ()的返回值,就是迭代器。
for 循环 遇到 迭代器,就执行 next( ) 方法就行了。
for 循环 遇到 可迭代对象,要先通过 可迭代对象.__iter__ ( )方法获取迭代器然后继续执行next( )方法。
1 class Foo: 2 3 def __init__(self,name,age): 4 self.name = name 5 self.age = age 6 def __iter__(self): 7 return iter([11,22,33,44]) 8 9 li = Foo(‘liufeiduo‘,22) 10 #1.获取li对象的类 Foo 中的__iter__ 方法,并获取其返回值。 11 #2.去循环上一步中返回的对象。 12 for i in li: 13 print(i) # 11/r 22/r 33/r 44/r
3. metaclass 类的祖宗
a. 在Python中,一切事物都是对象。
b.
class Foo():
pass
obj = Foo()
# obj 是对象,Foo 是类。
# Foo 类也是一个对象,type 的对象。
c. 类都是 type 类的对象 type(...)
"对象"都是类的对象 类()
1 class MyType(type): 2 def __init__(self,*args,**kwargs): 3 print(‘123‘) 4 pass 5 6 7 class Foo(object,metaclass=MyType): 8 def func(self): 9 print(‘hello‘) 10 11 # 执行结果: 123
类后面加括号,创建对象并不是直接执行了该类的 __init__ 方法,先执行 type 的 __call__ 方法,再执行该类的 __new__ 方法,再然后执行了 __init__ 方法。
4. 异常处理
1 #-----------------最基本的--------------------- 2 while True: 3 try: 4 inp = input(‘请输入序号:‘) 5 # 代码块,逻辑 6 i = int(inp) 7 except Exception as e: 8 # e 是Exception的对象,对象中封装了错误信息。 9 # 上述代码块出错,自动执行当前块内容。 10 print(e) 11 i = 1 12 13 print(i) 14 15 #--------------写异常的基本流程-------------------------------- 16 try: 17 int (‘w3rs‘) 18 except IndexError as e: 19 print(‘IndexError‘,e) 20 except ValueError as e: 21 print(‘ValueError‘,e) 22 except Exception as e: 23 print(‘Exception‘,e) 24 25 else: 26 print(‘else‘) 27 28 finally: 29 print(‘....‘) 30 #--------------------------------------------
写异常时,先 except ‘小弟’,后写‘大哥’,else 后面是没有捕捉到错误时执行,finally 后是无论如何都会执行。
主动抛出异常
1 try: 2 raise Exception(‘我是主动抛出的异常‘) # 主动触发异常 3 except Exception as e: 4 print(e) 5 # 执行结果:我是主动抛出的异常
主动触发异常的小应用(记录错误日志)
1 def db(): 2 #return True 3 return False 4 5 def index(): 6 try: 7 result = db() 8 if not result: 9 #打开文件,写日志 10 raise Exception(‘数据库处理错误‘) #当数据库返回值为False时,主动抛出异常,记录日志。 11 12 except Exception as e: 13 str_error = str(e) 14 print(str_error) 15 #打开文件写日志 16 17 index()
自定义异常
1 class LfdError(Exception): 2 3 def __init__(self,msg): 4 self.message = msg 5 6 def __str__(self): 7 return self.message 8 9 obj = LfdError(‘liufeiduo‘) 10 print(obj) 11 12 try: 13 raise LfdError(‘我错了‘) 14 except LfdError as e: 15 print(e)
断言 assert + 条件 如果满足条件,继续执行,若不满足条件,直接报错。用于强制用户服从,不服从就报错,可捕获但一般不捕获。
5. 反射
在Python 中执行反射效率蛮高的。
通过字符串的形式操作对象中的成员:
①getattr方法,到某某东西中获取某某内容。
1 class Foo: 2 def __init__(self,name,age): 3 self.name = name 4 self.age = age 5 6 def show(self): 7 return "%s-%s" %(self.name,self.age) 8 object = Foo(‘liufeiduo‘,22) 9 10 # b = "name" 11 # print(object.__dict__[b]) 12 inp = input(‘>>>>>>>>>>‘) 13 #去什么东西里面获取什么内容 14 b = getattr(object,inp) 15 16 print(b) #liufeiduo
②hasattr方法,去检测对象中是否有某成员,返回True、False。
③setattr方法,在对象中主动设置某个值。
1 class Foo: 2 def __init__(self,name,age): 3 self.name = name 4 self.age = age 5 6 def show(self): 7 return "%s-%s" %(self.name,self.age) 8 object = Foo(‘liufeiduo‘,22) 9 10 11 setattr(object,‘love‘,‘chengjunfei‘) 12 print(object.love) #chengjunfei
④delattr方法,将主动设置的某个值删除掉。
反射在模块之间也是可以用的。
6.单例模式
class Foo: __v = None @classmethod def get_instance(cls): if cls.__v: return cls.__v else: cls.__v = Foo() return cls.__v object1 = Foo.get_instance() print(object1) object2 = Foo.get_instance() print(object2) # 执行结果: #<__main__.Foo object at 0x000001137E007908> #<__main__.Foo object at 0x000001137E007908>
好处:内存中对象只创建一份就可以了,
以上是关于Python 3学习 ——面向对象的主要内容,如果未能解决你的问题,请参考以下文章