面向对象进阶篇
Posted 叶祖辉
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象进阶篇相关的知识,希望对你有一定的参考价值。
上节补充
当创建对象的类中没有我们想要执行的方法是,我们知道应该从它的父类里面找,如果父类里面有我们想找的方法,而且放下下面又包含方法时,包含的方法怎么执行呢?
class A: def f1(self): print("A") def xxx(self): print("111") class B: def f1(self): self.xxx() print("B") def xxx(self): print("222") class C(): def f2(self): print("C") def xxx(self): print("444") class D(C,B): def f(self): print("D") obj = D() obj.f1()
我们知道对象可以执行自己的构造方法,那么我们既想对象执行自己的构造方法,又想执行父类的构造方法怎么办呢?
1、super(当前类名,self).__init__() 推荐使用
2、父类名.__init__(self)
class annimal: def __init__(self): self.name = "动物" print("构造方法A") class cat(annimal): def __init__(self): self.tp = "喵" print("构造方法B") # super(cat,self).__init__() annimal.__init__(self) obj = cat() print(obj.__dict__) #表示对象内所封装的成员 构造方法B 构造方法A {\'name\': \'动物\', \'tp\': \'喵\'}
派生类继承父类中init及方法中包含方法,找寻的思路(查找源码的过程)
如果派生类里面没有__init__构造方法,则去其父类中寻找(必须有继承关系)
class annimal: def __init__(self): print("构造方法A") def f1(self): print("111") class cat(annimal): def __init__(self): self.f1() print("构造方法B") super(cat,self).__init__() obj = cat() # cat()执行cat中__init__方法,__init__方法下又有self.f1 cat中没有f1方法去annimal中找 111 构造方法B 构造方法A
通过反射:通过类自能找类的成员
通过对象既可以找对象里面的成员又可以找类里面的成员
本章将重点讲解python类的成员,成员修饰符,类的特殊成员
一、类的成员
类的成员可以分为三大类:字段、方法、特性
class qwe: age = 10 #静态字段 def __init__(self,name): #构造方法 self.name = name # 普通字段 def f1(self): # 普通方法 print("123") @staticmethod #静态方法 def f2(args,args1): print("zxx") @classmethod #类方法 def f3(cls): print(cls) @property #特性(将方法伪造成字段) def f4(self): temp = self.name return temp @f4.setter def f4(self,value): print(value) self.name = value a = qwe("111") a.f1() qwe.f2(1,2) qwe.f3() print(a.f4) a.f4 = 456 print(a.f4)
注:所有成员中,只有普通字段的内容保存在对象中,既根据此类在对象中创建了多个对象,在内存中就有多少个普通字段,而其他的成员,则都保存在类中,既无论对象多少,内存中只有一份
1、 类成员
由上图可是:
- 静态字段在内存中只保存一份
- 普通字段在每个对象中都要保存一份
字段分为:普通字段: 普通字段属于对象,普通字段用于对象有不同标签的情况
静态字段: 静态字段属于类,将每个对象中存在的东西在类中保存一份(多个方法共同用到的参数)
方法分为:普通方法: def xxx(self)必须创建对象来访问方法
静态方法: 通过在方法前加@staticmethod 而且方法中不用加self,而可以有其他参数 @staticmethod 不需要创建对象来访问方法
def xxx()
类方法:通过在方法前加@classmethod 而且方法中必须有cls(当前类的类名) @classmethod
def xxx(cls)
特性:通过在方法前加@property将方法伪造成一种字段(以字段的形式访问方法)参数只能是一个self @property
通过 对象.方法(方法后没有括号)obj.f1 def xxx(self)
下面的用于设置值
@property def f4(self): temp = self.name return temp @f4.setter def f4(self,value):
class qwe: age = 10 #静态字段,存在类中 def __init__(self,name): #构造方法,存在了类中 self.name = name # 普通字段,存在对象中 def f1(self): # 普通方法,存在类中 print("123") @staticmethod #静态方法 def f2(args,args1): print("zxx") @classmethod #类方法 def f3(cls): print(cls) @property #特性(将方法伪造成字段) def f4(self): temp = self.name return temp @f4.setter def f4(self,value): print(value) self.name = value a = qwe("111") a.f1() qwe.f2(1,2) qwe.f3() print(a.f4) qwe.f4 = 456 print(a.f4)
规定:自己的成员自己去访问(除了类中的普通方法(本身也可以但是我们不这样做))
通过类访问: 静态字段,静态方法、类方法(静态方法的特殊情况)
通过对象访问:静态字段,类的普通方法、类的特性
成员 :字段 :静态字段(每个对象都有一份),普通字段(每个对象都不同)
方法 :静态方法(无需使用对象封装的内容),普通方法(使用对象封装的内容),类方法()
特性 :普通特性(将一个方法伪造成字段的方式访问)
快速判断调用:有self==>对象调用
无self==>类调用
2、类成员的修饰符
类的所有成员在上一步骤中已经做了详细的介绍,对于每一个类的成员而言都有两种形式:
- 公有成员,在任何地方都能访问
- 私有成员,只有在类的内部才能方法
私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:__init__、__call__、__dict__等)
class C: def __init__(self): self.name = \'公有字段\' self.__foo = "私有字段"
静态字段
公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
私有静态字段:仅类内部可以访问;
class C: def __init__(self): self.foo = "公有字段" def func(self): print self.foo # 类内部访问 class D(C): def show(self): print self.foo # 派生类中访问 obj = C() obj.foo # 通过对象访问 obj.func() # 类内部访问 obj_son = D(); obj_son.show() # 派生类中访问
class C: def __init__(self): self.__foo = "私有字段" def func(self): print self.__foo # 类内部访问 class D(C): def show(self): print self.__foo # 派生类中访问 obj = C() obj.__foo # 通过对象访问 ==> 错误 obj.func() # 类内部访问 ==> 正确 obj_son = D(); obj_son.show() # 派生类中访问 ==> 错误
1、对于自己私有的自由自己能访问,其派生类和父类都不能访问(意思就是在自己内部可以访问)
成员修饰符:公有 任何地方都可以访问
私有 只有在自己内部才可以访问,也可以在外部间接的访问私有的
如果在外面非要访问私有字段的话也可以通过 对象_类名__字段(或方法)
面向对象中一些常用特殊方法:__init__ 、__del__ 、
class Foo: __metaclass__ = MyType #表示类由谁创建 def __init__(self): #r = Foo() 实例化对象 print("xxx") def __call__(self,*args,**kwargs): #r() 执行此方法 print("xxx") return 1 def __getitem__(self, item): #r["xxx"]和r[x:x] 执行此方法 print(item) def __setitem__(self, key, value): #r["xxx"] = 123 执行此方法 print(key,value) def __delitem__(self, key): #del r["xxx"] 执行此方法 print(key)
__dict__获取类或对象里面的成员,用法:xxx.__dict__
__doc__获取注释
r = Foo() #在类后面加括号执行__init__
r() #在对象后面加括号执行__call__
m = Foo()() #先Foo()实例化一个对象执行__init__,再在对象后面加括号执行__call__
print(m) #获取对象加括号的返回值
2、异常处理
为了防止程序报一些未知的错误,不让用户看到大黄页(错误信息),而是可以把此转化到类外一个人性化的界面
inp = input("请输入内容:") try: #try里面就是捕获错误 num = int(inp) print(num) except IndexError as e: #IndexError 表示捕捉索引错误(特定的错误) print("索引错误") except Exception as e: #这里的e表示封装了错误信息的对象,Exception表示所有类型错误的集合,是所有错误类的基类 print(e)
异常其他结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
try: # 主代码块 pass except KeyError,e: # 异常时,执行该块 pass else: # 主代码块执行完,执行该块 pass finally: # 无论异常与否,最终执行该块 pass |
主动触发异常
1
2
3
4
5
6
7
|
try: raise Exception(\'错误了。。。\') except Exception,e: print e |
自定义异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class WupeiqiException(Exception): def __init__(self, msg): self.message = msg def __str__(self): return self.message try: raise WupeiqiException(\'我的异常\') except WupeiqiException,e: print e |
断言
1
2
3
4
5
|
# assert 条件 assert 1 == 1 assert 1 == 2 |
以上是关于面向对象进阶篇的主要内容,如果未能解决你的问题,请参考以下文章