上节补充
当创建对象的类中没有我们想要执行的方法是,我们知道应该从它的父类里面找,如果父类里面有我们想找的方法,而且放下下面又包含方法时,包含的方法怎么执行呢?
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)
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类) ;代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的
ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError
异常其他结构
try: # 主代码块 pass except KeyError,e: # 异常时,执行该块 pass else: # 主代码块执行完,执行该块 pass finally: # 无论异常与否,最终执行该块 pass
主动触发异常
try: raise Exception('错误了。。。') except Exception,e: print e
自定义异常
class WupeiqiException(Exception): def __init__(self, msg): self.message = msg def __str__(self): return self.message try: raise WupeiqiException('我的异常') except WupeiqiException,e: print e
断言
# assert 条件 assert 1 == 1 assert 1 == 2