pickle.load:切记,如果写入文件的是类,一定要先导入相关的类
一、上节回顾补充
二、面向对象(下) 成员
1、字段 2、方法 3、属性
三、成员修饰符
四、特殊成员
五、面向对象边缘
六、异常处理
七、设计模式之单例模式
一、上节回顾补充
面向对象基本知识:
1、类和对象的关系
2、三大特性: 封装、继承、多态(多种形态、多种类型)
多态:
def func(arg): #python中不用指定参数arg类型 print(arg) func(1) #可以三数字 func("alex") #可以三字符串 func([11,22,33,]) #可以三列表
在C#/java中 必须制定参数类型,下面用python的方式举例:
def func(A arg): #必须指定类型 print(arg) func(123) func("alex") #报错(如果不是int类型就报错) class A: pass class B(A): pass class C(A): pass #arg 参数:必须是A类型或A的派生类类型 def func(A arg): #这里必须指定父类A,但arg的类型的类型可以三A、B、C print(arg)
二、面向对象中 成员
字段:
静态字段、普通字段
ps:静态字段在代码加载时已经创建
class foo: #字段(静态字段)属于类,用类调用 cc = 123 def __init__(self): #字段(普通的字段)保存在对象里,用对象调用 self.name = ‘alex‘ #如果没有创建对象,那么内存里就没有普通字段
一般情况:自己访问自己的字段
class Province: country = "中国" def __init__(self,name): self.name = name hn = Province("河南") hb = Province("河北") print(hn.name) # 在对象里用对象访问 print(Province.country) # 在类里用类访问 # 在Python里也可以用对象访问静态字段 print(hn.country)
规则:
普通字段只能用对象访问
静态字段用类访问(万不得已不要用对象访问)
方法: 所有方法属于类(在其他语言里只有两种方法)
1、普通方法:至少一个self,对象执行
2、静态方法:任意参数,没有self,类执行
3、类方法:至少有一个cls参数,由类执行
class Province: country = "中国" def __init__(self,name): self.name = name #普通方法,由对象去调用执行(方法属于类) def show(self): print(self.name) #静态方法,由类调用执行(操作1、2、之后变成静态方法) @staticmethod #2、加上@staticmethod def f1(): #1、参数里去掉self,可以有其他参数 print("....") #类方法(静态方法的一种) @classmethod def f2(cls): #至少必须有一个参数cls,自动传递参数返回类名 #cls #类名,()创建对象 #cls() print(cls) #类名<class ‘__main__.Province‘> def f3(self): return self.name[1] obj = Province("河南") obj.show() Province.f1() Province.f2() #<class ‘__main__.Province‘> ret = obj.f3() print(ret) #南
属性:
不伦不类的东西
具有方法的写作形式,具有字段的访问形式
class Page: def __init__(self,all_count): self.all_count = all_count @property #属性就需要加上property这个方法 def all_pager(self): a1,a2 = divmod(self.all_count,10) if a2 == 0: return a1 else: return a1 + 1 @all_pager.setter #函数名.setter ,设置 def all_pager(self,value): #函数名都和上一个相同 print(value) @all_pager.deleter # 删除 def all_pager(self): print("del") #all_pager没有加上属性之前,用下面形式操作 #p = Page(101) # r = p.all_count #字段 # result = p.all_pager() #方法 # print(result) #all_pager加上属性之后 p.all_count = 102 del p.all_count #删除方法的字段 ret = p.all_pager #属性 (属性和方法区别就是少了括号) print(ret) p.all_pager = 111 #用属性重新定义 del p.all_pager #用属性删除,伪删除动作,里面执行什么自己定义的
另一种属性
class Pager: def __init__(self,all_count): self.all_count = all_count def f1(self): return "f1" def f2(self,value): print(value) def f3(self): print("f3") foo = property(fget=f1,fset=f2,fdel=f3) #还可以按顺序直接给值 p = Pager(101) ret = p.foo print(ret) obj = Pager(110) obj.foo = "f2" del obj.foo #结果 f1 f2 f3
三、成员修饰符
私有的: 只能类自己本身的成员访问调用,其他类不能访问
公有的: pass
class Foo: def __init__(self,name,age): self.__name = name #加两个下划线,只能在类的内部访问,外部访问不到 self.age = age def f1(self): print(self.__name) class Bar(Foo): def f2(self): print(self.age) #这里如果写成self.__name则外面获取obj1.f2()会报错 obj = Foo("alex",13) #print(obj.__name) #会报错,外部不能访问 obj1 = Bar("Q",12) obj1.f2() #继承也不能执行__name,只能本身类内部访问 obj1.f1()#print(obj._Foo__name) #(可以取到私有的,不到万不得已不要强制访问)
四、特殊成员
构造方法 __init__
析构方法 __del__ :垃圾清除之前自动执行 类的__del__方法(有就执行没有不执行)
__call__ :对象加括号,就会自动执行__call__方法
__str__:直接打印对象,就会自动执行__str__方法
__getitem__:获取
__setitem__:设置
__delitem__:删除
class F: #构造方法 def __init__(self,name,age): self.name =name self.age =age #析构方法 def __del__(self): pass def __call__(self, *args, **kwargs): print("123") def __str__(self): return "%s" % self.name def __getitem__(self, item): # print(item.start)#obj[1:2] 中的1 # print(item.stop)#2 # print(item.step) #步长 return "getitem" def __setitem__(self, key, value): #key.star key.stop key.step return "setitem" def __delitem__(self, key): # key.star key.stop key.step print("del item") p = F("QL",12) print(p.__class__) #<class ‘__main__.F‘> obj = F("QL",15) #语法对应关系 ret = obj["ad"] # 自动执行getitem方法,自动赋值给item ret1 = obj[1:2] #切片 会执行getitem方法 print(ret1) obj[1:4] = [11,22,33,44,55,66,] #自动执行setitem方法 del obj[1:3] #自动执行 delitem print(obj) #直接打印对象,就会自动执行__str__方法 obj() #对象加括号,就会自动执行__call__方法 # #ret = obj["k1"] = 111 #自动执行setitem方法 # #print(ret) # # del obj["k1"] #自动执行delitem方法 obj() #加上__call__方法才能执行(对象后加括号) #F()() #也可以写成这样 print(obj) #不加str会输出内存地址<__main__.F object at 0x0000000000726630>,加上__str__会友好显示,str里返回什么就输出什么 #__dict__ #获取对象中封装的数据 【重要】 ret = obj.__dict__ print(ret) #{‘age‘: 12, ‘name‘: ‘QL‘} #print(F.__dict__)#获取类中的成员
__iter__
class F1(): def __iter__(self): #iter是生成器(里面有yield就是生成器) #yield 1 #yield 2 return iter([11, 22, 33, ]) obj = F1() for item in obj:#默认不可以迭代,加上iter方法才可以迭代 print(item)#默认执行iter方法,迭代iter返回值
五、面向对象边缘
- insinstance 查看某个对象是不是某个类创建的
- issubclass 查看某个类是不是某个类的子类
class A: pass class B(A): pass obj = A() ret = isinstance(obj,B) class Bar: pass class Foo(Bar): pass obj = Foo() #obj,Bar(obj类型和obj类型的父类)的实例 ret2 = isinstance(obj,Bar) #查看obj是不是Bar创建的 print(ret2) #True ret1 = issubclass(Bar,Foo)# 查看Bar 是不是Foo的子类 print(ret1) #False
主动执行父类方法:
class C1: def f1(self): print("c1.f1") class C2(C1): def f1(self): # # 主动执行父类的f1方法 super(C2,self).f1() print("c2.f1") #C1.f1(self) #不建议使用,用上面的super方法 obj1 = C2() obj1.f1()
有序字典
class MyDict(dict): def __init__(self): self.li = [] super(MyDict, self).__init__() def __setitem__(self, key, value): self.li.append(key) super(MyDict, self).__setitem__(key,value) def __str__(self): temp_list = [] for key in self.li: value = self.get(key) temp_list.append("‘%s‘:%s"% (key,value)) temp_str = "{" + ",".join(temp_list) + "}" return temp_str obj = MyDict() obj["k1"] = 123 obj["k2"] = 456 print(obj) #继承父类的setter #结果 {‘k1‘: 123, ‘k2‘: 456}
六、异常处理
while True: num1 = input(‘num1:‘) num2 = input(‘num2:‘) try: li = [11, 22] print(‘li[100]‘) #indexerro num1 = int(num1) num2 = int(num2) result = num1 + num2 except ValueError as ex: #只捕获ValueError错误 从上往下捕获 print(‘ex‘) except IndexError as ex: print(‘ex‘) except Exception as ex: # ex 是Exception的一个对象,Exception捕获所有错误 print(‘ex‘) # str
完整代码块
try: pass except ValueError as ex: print(ex) except Exception as ex: print(ex) else: #上面不报错执行else pass finally: #不管报不报错都执行finally pass
主动触发异常
try: raise Exception(‘主动错误一下‘) #self.message = ‘主动错误一下’ print(1234) except ValueError as ex: print(ex) except Exception as ex:#__str__,return self.message print(ex) else: #上面不报错执行else pass finally: #不管报不报错都执行finally pass
断言
assert 1==1 #如果条件成立不报错 assert 1==2 #如果条件不成立报错 p = obj() p.start() #在执行start之前先执行一个 p.status == False,就可以在start中写入(assert p.staus == False)
七、设计模式之单例模式(23种,推荐书《goF设计模式》)
单例模式: 用来创建单个实例
class Foo: instance = None def __init__(self,name): self.name = name @classmethod def get_instance(cls): #cls 类名 if cls.instance: return cls.instance else: obj = cls("alex") #一般是固定值,也可以传参 cls.instance = obj #对象赋值给instance return obj obj1 = Foo.get_instance() print(obj1) obj2 = Foo.get_instance() print(obj2)
谁来访问都创建一个,比较浪费,不如只创建一个,都来访问这一个。