python09-面向对象(二) & 异常
2017-05-11 本文已影响0人
AndroidCat
面向对象
-
回顾:
- 反射:以字符串的形式去某个对象(模块,类,对象)操作它的成员(python中,一切皆对象)
# 从模块中获取属性 module = __import__('commons') # 引入commons模块 if __name__ == '__main__': if hasattr(module, 'f1'): # print('ok') f1 = getattr(module, 'f1') ret = f1() print('ret =', ret) # 从类中获取属性 class Cat: desc = 'YHH' def __init__(self, name): self.name = name def show(self): print(self.name) show = getattr(Cat, 'show') show(Cat('yhh')) # 从对象中获取属性 cat = Cat('yhh') show = getattr(cat, 'show') show()
- 多继承面试题:
# 继承关系: # A(ooo) --> D # B(ooo) --> C(xxx,ooo) --> D class D(A,C): pass dog = D() # 创建D实例 dog.xxx() # 调用xxx方法,只有C有,调用C的 # 在xxx方法内部调用ooo方法,虽然C也有ooo方法 # 但是函数内部调用方式为:self.ooo() # 根据继承的调用顺序,虽有调用的是A的ooo方法 # 看别人的代码时,惊颤遇到这个问题--方法由谁发起的就由谁开始找
- 继承中调用构造方法
- 创建对象时会调用对象的__init__方法
- 如果对象没有__init__方法,回去调用父类的构造方法
class Animal: def __init__(self): print('Animal') class Cat(Animal): def __init__(self): print('Cat') cat = Cat() # Cat # ===================== class Animal: def __init__(self): print('Animal') class Cat(Animal): # def __init__(self): # print('Cat') pass cat = Cat() # Animal
- 调用父类的构造方法
- 调用父类的构造方法有两种方式:
# 一:第一个参数为当前类,第二个参数为self # 表示找到Cat的父类并执行构造方法 class Animal: def __init__(self): print('Animal') class Cat(Animal): def __init__(self): print('Cat') super(Cat, self).__init__() cat = Cat() # Cat Animal # 二:主动去调用父类的构造方法 class Animal: def __init__(self): print('Animal') class Cat(Animal): def __init__(self): print('Cat') Animal.__init__(self) cat = Cat() # Cat Animal
-
成员:
- 反射:
- 通过类-对象指针也能找到类中的方法
class Cat(): def __init__(self, name): self.name = name def show(self): print(self.name) cat = Cat('yhh') ret = hasattr(Cat, 'show') # 类中的方法 print(ret) # True ret = hasattr(cat, 'name') # 对象的属性 print(ret) # True ret = hasattr(cat, 'show') # 对象的方法 print(ret) # True
- 手动实现从导入模块到创建对象再获取对象属性的反射
module = __import__('commons', fromlist=True) class_name = getattr(module, 'Cat') cat = class_name('yhh') name = getattr(cat, 'name') print(name) # yhh method = getattr(cat, 'show') method()
-
静态字段:静态字段存在类中
- 如果一个类中所有的对象都用共同的字段且想通过,可将此字段设置为静态字段
- 在类中存在的字段为静态字段,在对象中存在的字段为普通字段
class Province: country = 'China' # 静态字段
-
类的成员:普通字段,普通方法,静态字段,静态方法,类方法,特性
- 约定俗成:普通字段,普通方法由对象访问,静态字段,静态方法,类方法由类访问
- 通过类访问普通方法需要参数需要传入对象
-
静态方法
class Cat: @staticmethod def show(): pass
- 类方法
- 类方法其实相当于静态方法的另一种形式,只是调用时python自动将类名传给方法
class Cat: @classmethod def show(cls): print(cls) Cat.show()
-
特性(属性)
- 执行方法一般为对象名.方法名()来调用,如果在定义方法的时候加上@property,那么调用该方法是不需要加上括号(前提是该方法不需要参数)
- 当方法名和字段名相同,写在后面的会覆盖前面的,一般不会这么写
- 作用:把方法伪造成字段来操作(比较鸡肋)
class Cat: def __init__(self, name): self.name = name @property def show(self): print(self.name) cat = Cat('yhh') cat.show cat.name # 获取字段 cat.name = 'newName' # 修改字段 cat.show # 通过特性,以字段的形式调用函数 cat.show = 'haha' # 报错 # 如果想要不报错,则修改代码 class Cat: def __init__(self, name): self.name = name @property def show(self): print(self.name) @show.setter def show(self,arg): self.name = arg cat = Cat('yhh') cat.show cat.show = 'catName' cat.show # 定义一个和@property方法名一样的方法,方法加上@方法名.setter就可以使得方法可以像修改属性一样传递参数
- 反射:
-
修饰符:
- 在方法或者字段前加上__表示私有
- 私有的方法和属性不能被继承,只有自己能够访问
- 私有也可以获取:
- python中有个特殊的方法,私有的实行和方法也可以获取,一般不会这么用
class Cat: __xo = 'xo' def __show(self): print('show') def pub(self): self.__show() cat = Cat() print(cat._Cat__xo) # 对象._类名__属性名或方法
-
特殊方法:
- __init__:构造方法,创建对象的时候调用
- __del__:解析器销毁对象的时候调用
- __call__:当调用对象名()的时候调用
- Django,web框架的源码用到
class Cat: def __init__(self): print('创建对象的时候调用') def __call__(self, *args, **kwargs): print('对象名()调用') cat = Cat() # 调用构造方法 cat() # 调用call方法
- __setitem__,__getitem__,__delitem__
- 自定义section会用到
- __str__
li = list([11, 22, 33, 44]) # ls是一个对象 print(li[1]) # 对象名[index] li[1] = 'index' # 对象名[index] = value del li[1] # del 对象名[index] print(li) # 打印对象 print(str(li)) # str(对象名) # li是list类的一个对象,通过类似的,我们自己创建的一个对象 class Cat: def __getitem__(self, item): print('getitem', item) def __setitem__(self, key, value): print('setitem', key, value) def __delitem__(self, key): print('delitem', key) cat = Cat() cat[1] # getitem 1 cat['k1'] # getitem k1 cat['key'] = 'value' # setitem key value del cat['key'] # delitem key # 通过切片时: cat = Cat() cat[1:2:3] # getitem slice(1, 2, 3) cat[1:2:3] = 123 # setitem slice(1, 2, 3) 123 del cat[1:2:3] # delitem slice(1, 2, 3) # python2.7中操作切片时会调用: # __getslice__ # __setslice__ # __delslice__ # 在python3.x中会调用: # __getitem__ # __setitem__ # __delitem__ #========================== # 直接打印对象会调用对象的__str__() # 将对象转字符串也会调用__str__() class Cat: def __str__(self): return '调用str方法' cat = Cat() print(cat) print(str(cat))
- dict:查看成员(比较重要)
- 应用:自定义form框架的时候用
- 获取对象里面所有的字段
class Cat: def __init__(self, name): self.name = name def show(self): pass def fun(self): pass ret = Cat.__dict__ print(ret)# {'__module__': '__main__', 'fun': <function Cat.fun at 0x102173ae8>, 'show': <function Cat.show at 0x102173a60>, '__weakref__': <attribute '__weakref__' of 'Cat' objects>, '__dict__': <attribute '__dict__' of 'Cat' objects>, '__init__': <function Cat.__init__ at 0x1021739d8>, '__doc__': None} obj = Cat('yhh') ret = obj.__dict__ print(ret) # {'name': 'yhh'}
- iter:
- for循环对象时会调用__iter__方法
li = list([11, 22, 33, 44, 55]) for item in li: print(item) # li是list类的对象,for循环li对象时会遍历得到结果 # 自定义对象遍历: class Cat: def __iter__(self): yield 11 yield 22 yield 33 yield 44 cat = Cat() for item in cat: print(item)
-
__new__ & __metaclass__
- python中一切皆对象,类是对象,模块是对象,类创建的也是对象
- 解析器解析到class关键字就会创建类对象(默认由type创建)
class Cat: __metaclass__ = xxx # 表示由xxx来创建这个类 # 创建类: Cat = type(Cat, (object,),{"fun1":func} # type(类名,(基类,..),{成员})
异常
- 编程难免遇到报错,如web网页尽量避免大黄页,应该让用户看到有好的错误页面.
try:
# 需要保护的代码
li = [11, 2, 3]
ret = li[5]
except IndexError as IE:
# 遇到异常时执行的代码块
print(IE)
except Exception as e:
# 遇到异常时执行的代码块
print(type(e))
else:
# 没有异常时执行的代码块
print('no exception')
finally:
# 不管有没有异常都会执行的代码块
print('finally')
- 异常分类:
- 所有异常都是Exception的派生类
- 主动触发异常
raise Exception('异常')
try:
raise Exception('发生异常')
except Exception as e:
pass
- 断(意义不大)
assert 1 == 1
assert 2 == 1
# 如果为真,则真
# 如果为假,则抛异常
# 做测试用,限制软件的运行环境等