Python成长之路 面向对象编程进阶与异常处理
面向对象编程进阶的知识点
1、静态方法
2、类方法
3、属性
4、特殊成员方法
5、反射
6、异常处理
一、静态方法
与类无关,只能由类调用,不能够访问类中任何属性和方法。无默认参数,与类有关联的就是通过类来调用该方法
class Foo(object): def __init__(self,name): self.name = name def general_func(self): print('普通方法1') def general_func2(self): self.general_func() print('普通方法2') @staticmethod def stat_func(arg): # print(arg.name) 不可以调用类中属性和方法 print('静态放法') # f = Foo('beijing') # f.general_func2() # 普通方法调用可以调用类中的方法和属性 # Foo.stat_func('name') 正确的调用方式 # f = Foo('beijing') # f.stat_func(f) # 上面这种方法可以调用类中的方法和属性,因为传进去了实列把他们关联起来了 # 当静态放法不需要传参的时候无论如何都调用不了类中的属性和方法 # 上面的方法不建议使用,只建议通过类来调用静态方法,而不是通过实例。
二、类方法
由类调用,至少有一个cls参数。只能访问类中的变量。不能够访问实例变量
class Foo(object): country = 'china' def __init__(self,name): self.name = name def general_func(self): print('普通方法1') def general_func2(self): print(self.name) self.general_func() print('普通方法2') @classmethod def class_func(cls): print(cls.country) # print(cls.name) 不能够调用构造函数中的变量 cls.general_func( 'arg' ) # 必须要传参才能调用类种方法 print('类方法') Foo.class_func() # 类方法的调用
三、属性
属性的定义分为两种方式:
- 装饰器 即:在方法上应用装饰器
- 静态字段 即:在类中定义值为property对象的静态字段
装饰器方式:在类的普通方法上应用@property装饰器
经典类具有一种@property装饰器
而新式类具有三种@property装饰器分别为
- @property :获取
- @方法名.setter :修改
- @方法名.deleter :删除
class Fruit(object): def __init__(self): self.original_price = 15 @property def apple_price(self): new_price = self.original_price return new_price @apple_price.setter def apple_price(self,value): self.original_price = value @apple_price.deleter def apple_price(self,value): del self.original_price appl = Fruit() # 实例 print(appl.apple_price) # 输出苹果的价格 15 appl.apple_price = 20 # 修改苹果的价格 print(appl.apple_price) # 输出苹果的价格 20 del appl.apple_price # 删除苹果的价格 print(appl.apple_price) # 因为删除苹果价格所以会报错
静态字段方式,创建值为property对象的静态字段
静态字段的方式穿件属性时,经典类和新式类无区别,都含有的属性是获取、修改、删除
property的构造方法中有个四个参数
- 第一个参数是方法名,调用
对象.属性
时自动触发执行方法 - 第二个参数是方法名,调用
对象.属性 = XXX
时自动触发执行方法 - 第三个参数是方法名,调用
del 对象.属性
时自动触发执行方法 - 第四个参数是字符串,调用
对象.属性.__doc__
,此参数是该属性的描述信息
class Fruit(object): def __init__(self): self.original_price = 15 def get_price(self): new_price = self.original_price return new_price def set_price(self,value): self.original_price = value def del_price(self,value): del self.original_price PEOCE = property(get_price,set_price,del_price,'价格变动')#对应的四个参数 appl = Fruit() # 实例 print(appl.PEOCE) # 输出苹果的价格 15 appl.PEOCE = 20 # 修改苹果的价格 print(appl.PEOCE) # 输出苹果的价格 20 del appl.PEOCE # 删除苹果的价格 print(appl.PEOCE) # 因为删除苹果价格所以会报错
这个两种方式中注意第一种方式新式类和经典类有区别,而第二种方式新式类和经典类都一样。同样要注意两种方式的写法不同。
四、特殊成员
1、__doc__ 表示类的描述信息
class Animal(object): """ 这个类是关于动物描述 """ pass print(Animal.__doc__) # 这个类是关于动物描述
2、__init__ 构造函数,通过对类的实例化时(即创建对象),自动触发执行__init__函数
3、__del__ 析构函数,当实例化的对象在内存中被释放时,自动触发执行__del__
4、__module__ 和 __class__
__module__表示当前操作的实例化对象在那个模块中
__class__ 表示当前操作的1对象的类是什么
5、__dict__ 查看类或对象中所有的成员
class People(object): nationality = 'china' def __init__(self,name,sex): self.name = name self.sex = sex def run(self): print('可以奔跑') def sleep(self): print('能够睡觉') print(People.__dict__) # {'__weakref__': <attribute '__weakref__' of 'People' objects>, '__module__': '__main__', 'nationality': 'china', '__dict__': <attribute '__dict__' of 'People' objects>, '__doc__': None, '__init__': <function People.__init__ at 0x0000029AD21E11E0>, 'sleep': <function People.sleep at 0x0000029AD21E12F0>, 'run': <function People.run at 0x0000029AD21E1268>} people2 = People('Tom','M') print(people2.__dict__) # {'name': 'Tom', 'sex': 'M'}
6、__call__ 在对象后面加括号,自动执行 __call__方法
7、__str__ 如果一个类定义了__str__方法,那么在打打印实例化对象时,默认输出该方法的返回值
class People(object): def __str__(self): return 'Tom' people = People() print(people) # ‘Tom’
五、反射
def eat(): print('可以吃了') class Fruits(object): def __init__(self, name): self.fruits_name = name def juice(self, name): print('使用%s榨汁给%s喝'%(self.fruits_name,name)) fruits = Fruits('apple') choice = input('>>>:').strip() if hasattr(fruits, choice): # getattr判断一个对象obj里面是否有对应的name_str字符串的方法,有就返回True否返回False # g = getattr(fruits, choice) getattr根据字符串获取对应obj中方法的地址 # g('Tom') #调用该方法 # print(fruits.fruits_name) # 结果为apple # setattr(fruits, choice, 'tangerine') # 当判断是一个属性的时候我们可以改变属性的值 # print(fruits.fruits_name) # 结果为tangerine delattr(fruits, choice) print(fruits.fruits_name) # 会报错因为删除掉了fruits_name这个属性 else: # setattr(fruits, choice, eat) # 把外面的方法关联到类中可以在类中调用了 # getattr(fruits, choice)() # 这个就是在类中调用关联的方法如果关联的方法有参数那么就要传入参数 setattr(fruits, choice, 22) # 传入一个属性到对象中 print(getattr(fruits, choice)) #调用对象中的属性
动态导入模块
import importlib metaclass = importlib.import_module('import_lib.metaclass') print(metaclass.C().name) # import_lib = __import__('import_lib.metaclass') # c = import_lib.metaclass.C() # print(c.name) # 第一个导入的是metaclass模块 而第二种导入的是import_lib这个包 #官方推荐使用第一个
六、异常处理
为了使程序出现bug的时候不讲错误的提示信息显示给用户,而传给用户一个提示的页面。
异常处理的一般格式为
try:
pass
except Exception as e:
pass
下面是一个异常处理的例子
dic = {'name': 'Tom', 'age': 18} try: dic['sex'] except KeyError as e: print('输入的键%s不存在' %e)
在写程序的时候有的时候可能出现不止一种异常我们就可以重复使用except来捕获异常,当我们所有想到的异常一个都没有捕获时我们可以使用except Exception as e 来做最后的捕获,等还有一些其他、它关于捕获的例子
dic = {'name': 'Tom', 'age': 18} try: dic['sex'] except KeyError as e: print('输入的键%s不存在' %e) except ValueError as e: print(e) . . . except Exception as e: # 万能的捕获异常 print(e) else: pass # 当没出现错误的时候执行这个模块 finally: pass # 不管有没有出错都要执行这个模块
自定义异常
class CustomException(Exception): def __init__(self, msg): self.message = msg def __str__(self): return self.message try: raise CustomException('自定义异常') except CustomException as e: print(e)
断言语句
断言一般用于测试,如果测试结果为Flas,将抛出AssertionError异常
str = 'abc' assert type(str) is dict # 抛出AssertionError异常