Python 面向对象
面向对象
面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用
如何创建类,方法,对象?
class Father(): # 创建类 def __init__(self): # 构造方法(初始化), self = 对象(obj) pass def show(self): # 创建方法 return None obj = Father() # 1.创建对象 2. 调用__init__方法 obj.show() # 调用方法
面向对象的三大特征
1、封装
封装,就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
class Father(): def __init__(self,name,age): self.name = name self.age = age def show(self): print(self.name,self.age) obj = Father("kidd",16) obj2 = Father("jim",17)
2、继承
子类继承父类
class Father(): def basketball(self): print("I like basketball") def tennis(self): print("I like tennis") def swimming(self): print("I don't like swimming") class Son(Father): # 继承父类 # 当父亲和儿子都喜欢时 def basketball(self): # super(子类名,self).父类方法 super(Son,self).basketball() # 调用父类的方法 print("I like basketball,too") def tennis(self): Father.tennis(self) print("I like tennis,too") # 当父亲不喜欢,儿子喜欢时 # 重构 def swimming(self): print("I like swimming") son = Son() son.basketball() son.tennis() son.swimming() # 输出 I like basketball I like basketball,too I like tennis I like tennis,too I like swimming
多继承
class Grandfather(): def basketball(self): print("I like basketball -G") def soccer(self): print("I like soccer -G") class Father(): def basketball(self): print("I like basketball -F") def tennis(self): print("I like tennis -F") def swimming(self): print("I don't like swimming -F") class Son(Father,Grandfather): pass son = Son() son.soccer() # 儿子找 ---> 没找到 ---> 父亲找 ---> 没找到 ---> 祖父找 ---> 找到了 son.basketball() # 儿子找 ---> 没找到 ---> 父亲找 ---> 找到了 # 多继承特点 左侧优先 同一个根时,根最后执行
3、多态
Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态
同时执行多个方法
就是说执行了子类的方法,又同时执行父类的方法
super(type[, object-or-type])
class GrandFather(): def __init__(self): self.show() def show(self): print("GrandFather -- show") class Father(GrandFather): pass class Son(Father): def __init__(self): super(Son,self).__init__() s = Son()
当然了,我也可以不用super,直接用 类+方法
什么是字段,方法?
字段分为:
普通字段 (执行只能通过对象访问)
静态字段 (执行 可以通过对象访问 也可以通过类访问)
class Foo(): operator = "Kidd" # 静态字段 def __init__(self): self.other = "Jim" # 普通字段
方法分为:
普通方法 (由对象来调用)
静态方法 (由类直接调用)
类方法 (由类直接调用)
class Foo(): def general(self): # 普通方法 print("General method") @staticmethod # 静态方法 def sta(): print("Static method") @classmethod # 类方法 def cls(cls): print("class method")
property()
第一个参数是方法名,调用 对象.属性
时自动触发执行方法
第二个参数是方法名,调用 对象.属性 = XXX
时自动触发执行方法
第三个参数是方法名,调用 del 对象.属性
时自动触发执行方法
第四个参数是字符串,调用 对象.属性.__doc__
,此参数是该属性的描述信息
class Foo: def get_bar(self): return 'wupeiqi' # *必须两个参数 def set_bar(self, value): return 'set value' + value def del_bar(self): return 'wupeiqi' BAR = property(get_bar, set_bar, del_bar, '自定义解释') obj = Foo() obj.BAR # 自动调用第一个参数中定义的方法:get_bar obj.BAR = "alex" # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入 del Foo.BAR # 自动调用第三个参数中定义的方法:del_bar方法 obj.BAE.__doc__ # 自动获取第四个参数中设置的值:description...
成员修饰符
共有成员
私有成员, 指无法直接访问,只能间接访问
class Student(): def __init__(self): self.id = "001" # 共有字段 self.__name = "Kidd" # 私有字段 def common(self): # 共有方法 return self.id def __private(self):# 私有方法 return self.__name def callable(self): c = self.common() p = self.__private() # 间接的访问 return c,p s = Student() print(s.id) # 001 print(s.__name) # 报错 print(s.callable()) # ('001', 'Kidd') 只需要在字段,方法前加 __(两个下划线)即可变成私有
特殊成员
__init__ __call__ __int__ __str__
class Foo(): def __init__(self): print("init") def __call__(self, *args, **kwargs): print("call") def __int__(self): return 123 def __str__(self): return "str" f = Foo() # 类调用(),触发__init__方法 f() # 对象调用(),触发__call__方法 print(int(f))# 当对象调用int方法时,它先执行对象中的__int__方法 print(f) # 为什这条语句会直接触发__str__? # 因为 print 语句其实是 print(str()) , so---> print(str(f))
obj.__dict__
class Foo(): def __init__(self,name,age): self.name = name self.age = age def other(self): self.gender = "male" f = Foo("Kidd",16) dic = f.__dict__ # 将对象中封装的所有内容,通过字典形式返回 print(dic) # {'name': 'Kidd', 'age': 16}
__getitem__ __setitem__ __delitem__
# 对象[] 的操作 class Foo(): def __init__(self,name,age): self.name = name self.age = age self.__dic = self.__dict__ # 设置私有成员,获取对象中封装的所有内容 def __getitem__(self,item): # 查看时, f["name"] return self.__dic[item] def __setitem__(self, key, value): # 设置时, f["age"] = 17 self.__dic[key] = value def __delitem__(self, key): # 删除时,del f["age"] self.__dic.pop(key) f = Foo("Kidd",16) value = f["name"] f["age"] = 17 del f["age"]
class T(object): "实现单利" def __new__(cls, *args, **kwargs): if not hasattr(cls,"_instance"): cls._instance = super().__new__(cls) return cls._instance "构造方法" def __init__(self,l): self.l = l def __getitem__(self, item): if item >= 0 : for n,i in enumerate(self.l): if n==item: return i else: l = reversed(self.l) for n,i in enumerate(l,1): if n == abs(item): return i def __setitem__(self, key, value): print(key,value) def __delitem__(self, key): print(key) t = T(list(range(1,11))) print(t[-1]) t["l"] = 0 del t["l"]
__iter___
class Foo(): def __iter__(self): a = [1,2,3] return iter(a) f = Foo() for i in f: print(i) # 如果类中有__iter__方法,对象 ---->可迭代对象 # for 循环类的对象 , 执行类中的__iter__方法 , 取返回值做可迭代对象
异常处理
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的代码 try: pass # 有异常 except Exception as e: print(e) # 无异常 else: print("No Exception") # 不管有没有异常,finally都要执行 finally: print("Try Finish")
自定义异常 与 主动触发异常
class Except(Exception): def __init__(self,error): self.error = error def __str__(self): return self.error try: raise Except("Custom Exception") # 主动触发异常 except Except as e: print(e)
断言
# 如果条件成立,程序继续执行 # 否则,报错 assert 1 == 1 assert 1 == 2
映射
映射:通过字符串的形式操作对象中的成员,在python中,一切事物皆是对象
getattr hasattr setattr delattr
class Foo(): def __init__(self,name,age): self.name = name self.age = age def __call__(self, *args, **kwargs): show = "%s - %s"%(self.name,self.age) return show def delete(self): return "delete" f = Foo("kidd",16) # 取字段 getattr(f,"name") # 取方法 getattr(f,"__call__") # 字段是否存在 hasattr(f,"age") # 方法是否存在 hasattr(Foo,"show") # 设置字段 setattr(f,"age",17) # 删除字段 delattr(f,"name") # 删除方法 delattr(Foo,"delete")
单例模式
如:让同学展示自己的姓名,年龄
class Students: def __init__(self,name,age): self.name = name self.age = age def __call__(self, *args, **kwargs): content = '''自我介绍 %s -- %s'''%(self.name,self.age) return content s1 = Students("kidd",16)() s2 = Students("bob",15)()
import time import threading import random class Member(object): _instance_lock = threading.Lock() def __init__(self): i = random.randint(1, 3) print(i) time.sleep(i) @classmethod def instance(cls, *args, **kwargs): if not hasattr(Member, "_instance"): with Member._instance_lock: if not hasattr(Member, "_instance"): Member._instance = Member(*args, **kwargs) return Member._instance def task(): obj = Member.instance() print(obj) for i in range(5): threading.Thread(target=task,).start()
class N(): def __new__(cls, *args, **kwargs): if not hasattr(N,'_state'): N._state = super().__new__(cls) return N._state def __init__(self): pass
单利模式的目的:保证当前内存中仅存在单个实例,避免内存浪费!
类中的cls,self指的是谁
cls:类本身
self:实例化后的对象
class T(object): def __new__(cls, *args, **kwargs): if not hasattr(cls,"_instance"): # T=cls,类本身 cls._instance = super().__new__(cls) return cls._instance def __init__(self): # t1=self,类实例后的对象 print(self) t1=T() t2=T()
其他相关
isinstance(obj, cls)
检查是否obj是否是类 cls 的对象
class Foo: def __init__(self): pass f = Foo() result = isinstance(f,Foo) print(result)
issubclass(sub, super)
检查sub类是否是 super 类的派生类
class Grandfather: pass class Father(Grandfather): pass class Son(Father): pass issubclass(Son,Father) # True issubclass(Son,Grandfather) # True