本节内容:
一. 面向对象中的成员
二. 成员修饰符,特殊成员
三. 异常处理
四. 设计模式之单例模式
(一). 面向对象中的成员(类的成员):
注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段。而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份。
1. 字段:
静态字段: 在内存中只保存一份, 属于类
普通字段: 在每个对象中都保存一份, 属于对象
1 class Province: 2 country = "中国" #静态字段 3 4 def __init__(self,name): 5 6 self.name = name # #字段(普通字段) 7 8 sx = Province("山西") 9 10 print(sx.name) #引用普通字段 11 print(Province.country) #引用静态字段 12 13 #输出: 14 15 山西 16 中国
总结:
普通字段只能用对象访问
静态字段用类访问(万不得已的时候可以是用对象访问)
PS: 静态字段在代码加载时候,就已经创建
2. 方法:
包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。
普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
静态方法:由类调用;无默认参数;
1 class Province: 2 country = "中国" 3 4 def __init__(self,name): 5 self.name = name 6 #普通方法:有对象去调用执行(方法属于类) 7 8 def show(self): 9 print(self.name) 10 11 @staticmethod 12 def f1(arg1,arg2): 13 # 静态方法,由类调用执行.(当方法内部不需要对象中封装的值时,可以将方法写成静态方法) 14 print(arg1,arg2) 15 16 @classmethod 17 def f2(cls): 18 #类方法 19 print(cls) 20 21 Province.f1(11,22) 22 Province.f2() 23 24 #输出: 25 26 11 22 27 <class '__main__.Province'>
3. 属性
定义时,在普通方法的基础上添加 @property 装饰器;属性仅有一个self参数。
调用时,不需要加括号
注意:属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象
1 class Pager: 2 3 def __init__(self, all_count): 4 self.all_count = all_count #定义用户访问总数据 5 @property 6 def all_pager(self): 7 a1, a2 = divmod(self.all_count,10) #默认一页10行数据 8 if a2 == 0: #判断余数是否为0,是则返回本身 9 return a1 10 else: 11 return a1 + 1 #否,则返回本身加1页 12 13 @all_pager.setter #定义设置属性 14 def all_pager(self,value): #给定变量参数,直接赋值即设置修改 15 print(value) 16 17 @all_pager.deleter #定义删除属性 18 def all_pager(self,value): #给定变量参数,直接删除。 19 print("del all_pager") 20 21 p = Pager(101) # 22 ret = p.Pager 23 print(ret) #获取 24 p.all_pager = 111 #修改 25 del p.all_pager #删除
注:
经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法
新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
属性的定义还有一种方式:
使用内置函数:fget, fset, fdel
参数fget是获取类成员的属性值;参数fset是设置类成员的属性值;fdel是删除类成员;
通过这个函数的方式,可以实现类成员变量隐藏的方式,也就是面向对象里封装的要求。
1 class Pager: 2 3 def __init__(self,all_count): 4 self.all_count = all_count 5 6 def f1(self): 7 return self.all_count 8 9 def f2(self,value): 10 self.all_count = value 11 12 def f3(self): 13 del self.all_count 14 15 foo = property(fget= f1, fset=f2, fdel=f3) 16 17 p = Pager(101) 18 19 result = p.all_count #输出类成员属性 20 print(result) 21 p.all_count = "hong" #设置类成员属性 22 result = p.all_count 23 print(result) 24 del p.all_count #删除类成员属性 25 26 101 27 hong
(二). 成员修饰符,特殊成员
私有成员: 只有在类自己成员的内部使用
公有成员: 在任何地方都可以使用
私有成员举例:
1 class Foo: #定义类Foo 2 3 def __init__(self,name): 4 self.__name = name 5 6 def f1(self): 7 print(self.__name) 8 9 class Bar(Foo): #定义类Bar继承类Foo 10 11 def f2(self): 12 print(self.__name) 13 14 obj = Bar("hong") 15 obj.f1() #f1属于类Foo的内部成员,可以访问,输出结果 16 obj.f2() #f2为类Bar虽然为继承关系,一样不能访问,报错。
公有成员举例:
1 class Foo: 2 3 __cc = "123" 4 5 def __init__(self, name): 6 self.__name = name 7 8 def f1(self): 9 print(self.__name) 10 11 @staticmethod 12 def f3(): 13 print(Foo.__cc) 14 15 obj = Foo("dddd") 16 obj.f1() 17 obj.f3() 18 Foo.f3() 19 20 dddd 21 123 22 123
特殊成员:
__call__ , __str__ , __dict__
1 class Foo: 2 #构造方法 3 4 def __init__(self,name,age): 5 self.name = name 6 self.age = age 7 8 #析构方法 9 def __del__(self): 10 pass 11 12 def __call__(self,*args,**kwargs): 13 print("call") 14 15 def __str__(self): 16 return "%s - %d" %(self.name, self.age) 17 obj = Foo()#对象执行init 18 obj() #对象执行call 19 Foo()() #通过类执行call 20 #构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()() 21 22 obj1 = Foo("hong",20) 23 obj2 = Foo("fei",19) 24 # 25 print(obj1) 26 print(obj2) 27 28 ret = str(obj1) 29 print(ret) 30 31 ret = obj1.__dict__ #dict为获取所有成员信息,字典格式 32 print(ret) 33 34 hong - 20 35 fei - 19 36 hong - 20 37 {'name': 'hong', 'age': 20}
__getitem__, __setitem__, __delitem__ : 主要用于索引操作,分别表示获取,设置,删除数据。
1 class Foo(object): 2 3 def __getitem__(self, key): 4 print ('__getitem__',key) 5 6 def __setitem__(self, key, value): 7 print ('__setitem__',key,value) 8 9 def __delitem__(self, key): 10 print ('__delitem__',key) 11 12 13 obj = Foo() 14 15 result = obj['k1'] # 自动触发执行 __getitem__ 16 print(result) 17 obj['k2'] = 'hong' # 自动触发执行 __setitem__ 18 del obj['k1'] # 自动触发执行 __delitem__ 19 20 __getitem__ k1 21 __setitem__ k2 hong 22 __delitem__ k1
(三).异常处理:
在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户看见大黄页!!!
1. 与python异常相关的关键字
raise:手动抛出/引发异常:raise [exception[,data]]
try/except:捕获异常并处理
pass:忽略异常
as:定义异常实例(except IOError as e)
finally:无论是否出现异常,都执行的代码
else:如果try中的语句没有引发异常,则执行else中的语句
except Exception as error:
python中的异常类型
AttributeError #试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError #无法引入模块或包;基本上是路径问题或名称错误 IndentationError #语法错误(的子类) ;代码没有正确对齐 IndexError #下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError #试图访问字典里不存在的键 KeyboardInterrupt #Ctrl+C被按下 NameError #使用一个还未被赋予对象的变量 SyntaxError #Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError #传入对象类型与要求的不符合 UnboundLocalError #试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它 ValueError #传入一个调用者不期望的值,即使值的类型是正确的
1 try ... expec 2 3 try: 4 block 5 6 except [exception1(,exception2...),[data…]]: 7 8 block 9 10 (else: block)
try: 1/0 except ZeroDivisionError as errorinfor: print(errorinfor) #输出详细错误信息:integer division or modulo by zero
try: print "Testing begins!" raise MyError #自己抛出一个异常,后面代码不执行. except MyError: print 'This a defined error!' except: print "Other error!"
- try ... finally
- finally 里面只是执行完成try中的代码后,必须执行的代码, 即使是 try中有异常抛出,也是会去执行finally
- 所以,一般情况下,finally里面执行的都是一些清理工作,比如:关闭文件描述符,释放锁等
- 注意,finally中,如果出现异常,外部如果没有相应的捕获机制,该异常会层层抛出,直到最顶端,然后解释器停止。一般在外层再加一次try except异常捕获
(四). 设计模式之单例模式
__new__()在__init__()之前被调用,用于生成实例对象。利用这个方法和类的属性的特点可以实现设计模式的单例模式。单例模式是指创建唯一对象,单例模式设计的类只能实例化一个对象。
class Singleton(object): __instance=None def__init__(self): pass def__new__(cls,*args,**kwd): if Singleton.__instance is None: Singleton.__instance=object.__new__(cls,*args,**kwd) return Singleton.__instance
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
单例模式的三个要点:
1. 某个类只能有一个实例。
2. 必须自行创建这个实例。
3. 必须自行向整体系统提供这个实例。
实现的角度也有三个要点:
1. 只提供私有的构建函数
2. 类定义中必须含有一个该类的静态私有对象
3. 类提供了一个静态的共有函数用于创建或获取他本身的静态私有对象。
能力有限,细细琢磨吧。。有些是参考大神之作。