day08 面向对象补充及单例模式
一、面向对象中的静态字段和普通字段
静态字段、和普通字段
使用规范:
普通字段只能用对象访问
静态字段用类来访问 (在Python中静态字段可以用对象访问也可以用类访问,但在其他语言中只能用类来访问静态字段,而且为防止在某种情况下报错,在使用静态字段时需用类来访问)
class Province: country = 'China' # 静态字段 静态字段是属于类的 当有无数个对象时,没个对象都有一个同样的字段,这样的话会浪费内存,所以设定一个静态字段,只需在内存里创建一次即可 def __init__(self, name): self.name = name # 普通字段 普通字段是属于对象的 每创建一个对象,就会在对象所存放的内存里创建一个对象的普通字段
二、静态方法、普通方法、类方法
静态方法
静态方法直接通过类来调用
当方法中不需要通过类中的值时,将方法写为静态方法
普通方法
由对象来调用,普通方法属于类
类方法
class Foo: def __init__(self, name): self.name = name def show(self): print(self.name) @staticmethod def static(): print("static method") @classmethod def clsmethod(cls): # cls 为类名 那么可以通过cls后面加括号cls()来调用类 print(cls) Foo.clsmethod() # 类只的所有方法: # 普通方法:至少一个self,通过对象来执行 # 静态方法:可以有任意个参数,通过类来执行(也可通过对象那个来执行,但不到万不得已不要这么做) # 类方法: 至少一个cls,通过类来执行(也可通过对象那个来执行,但不到万不得已不要这么做)
三、属性
具有方法的代码写作方式,具有字段的访问形式
@property @类名.setter @类名.deleter
class pager: def __init__(self, all_count): self.all_count = all_count @property def all_pager(self): # 调用时可以像普通字段一样取值 格式:对象名.字段名 a1, a2 = divmod(self.all_count, 10) if a2 == 0: return a1 else: return a1 + a2 @all_pager.setter # 调用时可以像普通字段一样赋值 格式:对象名.字段名 = xxx def all_pager(self, value): pass @all_pager.deleter def all_pager(self): # 调用时可以像普通字段一样删除值 格式:del 对象名.字段名 pass #调用 pp = pager pp_get = pp.all_pager pp.all_pager = 'xxx' del pp.all_pager class class_attr: #属性的另外一种形式 def f1(self): return 'test' def f2(self, value): pass def f3(self): pass foo = property(fget=f1, fset=f2, fdel=f3) #调用: p = class_attr() res = p.foo p.foo = 'xxx' del p.foo
四、多态
多态即多种形态,在运行时确定其状态,在编译阶段无法确定其类型,这就是多态。Python中的多态和Java以及C++中的多态有点不同,Python中的变量是弱类型的,在定义时不用指明其类型,它会根据需要在运行时确定变量的类型(个人觉得这也是多态的一种体现),并且Python本身是一种解释性语言,不进行预编译,因此它就只在运行时确定其状态,故也有人说Python是一种多态语言。在Python中很多地方都可以体现多态的特性,比如 内置函数len(object),len函数不仅可以计算字符串的长度,还可以计算列表、元组等对象中的数据个数,这里在运行时通过参数类型确定其具体的计算过程,正是多态的一种体现。有些朋友提出Python不支持多态,我是完全不赞同的.
Python以它这种独有的方式体现多态的根本原因我觉得有两点:1)Python是解释性语言;2)Python中变量是弱类型的。所以Python体现多态的方式和Java决然不同,但是不能因为同Java中体现多态的方式不同就认为Python不支持多态,这种想法过于片面。
来自: http://blog.csdn.net/chongtianfeiyu/article/details/21894005
五、特殊方法
#!/usr/bin/env python # _*_ conding:utf-8_*_ class Foo: #构造方法 def __init__(self,name): self.name = name #析构方法 进行垃圾回收时在内存中删除对象时,如果类中定义了析构方法时,执行析构方法中的内容的再删除 def __del__(self): pass #call方法 实例名() 实例名后面加括号调用该实例的call方法 def __call__(self, *args, **kwargs): pass #str方法 print(实例)时,未定义str方法时输出该实例的类名及在内存的中地址 定义后输出str方法里定义的内容 def __str__(self): pass #dict方法 获取对象中封装的数据 print(Foo.__dict__) #输出 {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__str__': <function Foo.__str__ at 0x0000000001116048>, # '__del__': <function Foo.__del__ at 0x000000000110BEA0>, '__call__': <function Foo.__call__ at 0x000000000110BF28>, # '__doc__': None, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__init__': <function Foo.__init__ at 0x000000000110BE18>} obj = Foo('test') print(obj.__dict__) #输出 {'name': 'test'} class foo: def __init__(self,name): self.name = name def __getitem__(self, item): print("getitem") def __setitem__(self, key, value): print("setitem") def __delitem__(self, key): print("del item") obj = foo('xuanouba') obj['xuanouba'] #结果 getitem obj['test'] = 'aa' print(obj.__dict__) #结果 setitem del obj['test'] #结果 del item #__iter__方法 当将对象放到一个for循环里时,自动执行对象的__iter__方法 class FOO: def __iter__(self): yield 1 yield 2 obj = FOO() for i in obj: print(i)
六、其他方法
super方法
#super方法 class Foo: def f1(self): print('Foo') class Bar(Foo): def f1(self): #主动执行父类的f1方法 super(Bar,self).f1() print('Bar') obj = Bar() obj.f1()
isinstance()方法
# isinstance() #eg: isinstance(obj,Foo) res = isinstance(obj,Bar) #判断obj实例是不是Bar类型 print(res) res = isinstance(obj,Foo) #(Foo是Bar的父类)判断是不是Bar类型的父类的类型 print(res)
issubclass()方法
# issubclass() #eg: issubclass(Foo,Bar) 判断Foo类型是不是Bar类型的子类
七、成员修饰符
#!/usr/bin/env python # _*_ conding:utf-8_*_ #成员修饰符: # 私有:只有类自己内部能访问,外部不能直接访问,在成员前加__(两个下划线),##也不能继承## #在外部也可访问私有字段或私有方法,类似obj._Foo__cc #对象名._类名私有静态字段名 !! 不到万不得已不要用!! class Foo: __cc = 'name' def __init__(self,name): self.__name = name def f1(self): """ 访问私有成员时,只能同过这样的方式,在内部调用,然后外部通过共有方法的方式来间接访问,私有静态字段也一样 :return: """ print(self.__name) def f2(self): print(Foo.__cc) p = Foo('test') # print(p.__name) #这样直接访问类的私有成员会报错 # print(Foo.__cc) #这样直接访问类的私有静态字段也会报错 class FOO: def __init__(self,name): self.name = name def __f1(self): print("私有f1") def f1(self): print("共有f1") obj = FOO('ALEX') # obj.__f1() #会报错,因为是私有方法 obj.f1()
八、实现有序字典
#!/usr/bin/env python # _*_ conding:utf-8_*_ #字典虽是无序的,但Python中的列表是有序的,利用这个特性,来实现的自定义的有序字典 class Mydict(dict): #继承Python提供的dict类 def __init__(self): self.li = [] #创建一个空列表 super(Mydict,self).__init__() #执行dict类中的__init__方法 def __setitem__(self, key, value): self.li.append(key) #往字典中添加新的键值对时将key 追加到列表中 super(Mydict,self).__setitem__(key,value) def __str__(self): temp_list = [] #设置一个临时空列表 for key in self.li: value = self.get(key) temp_list.append("'{}':{}".format(key,value)) #将每一对键值对以 "'a':1" 这样的方式作为一个字符串追加到临时列表中 temp_str = '{' + ",".join(temp_list) + '}' #最后已列表的形式返回给用户 return temp_str obj = Mydict() obj['a'] = 1 obj['b'] = 2 print(obj)
九、单例模式
class Foo: instance = None def __init__(self,name): self.name = name @classmethod def get_instance(cls): #类方法,通过类直接调用, if cls.instance: #如果现在已经有实例,则将实例直接返回给对象 return cls.instance else: #如果现在没有实例,那么创建一个实例,然后返回给对象 obj = cls('test') cls.instance = obj return obj # 这样的话每次实例化一个对象的时候,都返回的是同一个实例 obj1 = Foo.get_instance() obj2 = Foo.get_instance() print(obj1) print(obj2)
更多关于单例模式:
http://www.cnblogs.com/seesea125/archive/2012/04/05/2433463.html