1、上节回顾:
1、面向对象的基本知识
1、类和对象的关系
2、三大特征
封装
继承
多态:多种类型,多种形态,c#和java都是通过继承来实现多态的
def func(arg): print(arg) func("a") func(123) func([11,22,"aa"])
结果:
a 123 [11, 22, 'aa']
通过这个程序可以看出,我们在调用func函数的时候,并没有规定传入参数的类型。而在c#和java中,在def func(int arg)里面是要定义参数类型的
如果传入参数的类型不对,将无法进行调用,所以c#和java都是通过继承来实现这个功能的
3、面向中类成员
1、字段
普通字段
静态字段
PS:静态字段在代码加载时候,已经创建
我们在上一章学习的时候,类的用法如下:
class Province: def __init__(self,name): self.name=name self.country = "中国" hn=Province("河南") hb=Province("河北")
结果:
河南 中国 河北 中国
这样每次创建对象的时候,都会把相同的中国扔到内存里面, 但是我们今天学习了静态字段,我们的程序可以这样来写
class Province:
country="中国"
def __init__(self,name):
self.name=name
hn=Province("河南")
hb=Province("河北")
print(hb.name)
print(hb.country)
print(Province.country)
结果:
河北
中国
中国
这样就是把“中国”这个字段放到静态字段里面,每次调用累的时候,都会用到这个静态字段,这样就会节省内存
而且大家也会发现,这个静态字段,hn这个对象可以通过自己得到静态字段,也可以通过类直接访问静态字段
但是我们在使用的时候,尽量不要通过类来直接访问这个静态字段
一般情况就是:自己访问自己字段
规则:
普通字段只能用对象访问
静态字段用类访问(不到万不得已的时候可以使用对象访问)
2、方法
所有的方法属于类
普通方法:至少一个self有对象去调用执行(方法属于类)
静态方法:由类去调用,任意参数
类方法: 至少有一个cls,类执行
普通方法:由对象去调用执行(方法属于类)
class Province: def __init__(self,name): self.name=name self.country = "中国" print(self.name,self.country) hn=Province("河南")
这种就是普通方法
class Foo: def __init__(self,name): self.name=name def show(self): print(self.name) @staticmethod def f1(name): print(name) obj=Foo("heihei") obj.show() Foo.f1("haha")
结果:
heihei haha
这个就是静态方法,需要在类里面的某个方法前面添加一个@staticmethod,这样就实现了静态方法
class Foo: def __init__(self,name): self.name=name def show(self): print(self.name) @staticmethod def f1(name): print(name) @classmethod def f2(cls,a1): print(cls,a1) obj=Foo("heihei") obj.show() Foo.f1("haha") Foo.f2("oo")
结果:
heihei haha <class '__main__.Foo'> oo
这个就是类方法,比静态方法,多了一个功能就是自动把类名传进去
参数想传什么就传什么
3、属性
不伦不类的东西,具有方法的写左行驶,具有字段的访问形式
class Foo: def __init__(self,name): self.name=name @property def all_pager(self): a1, a2 = divmod(self.name, 10) if a2 == 0: return a1 else: return a1+1 p=Foo(101) # p.all_pager #字段 # r=p.all_pager()#方法 # print(r) ret=p.all_pager print(ret)
结果:
11
让方法以字段的方式去使用
这是一种使用属性的方法,里面定义了setter和del,在执行的时候直接调用类的方法
class Foo: def __init__(self,name): self.name=name @property def all_pager(self): a1, a2 = divmod(self.name, 10) if a2 == 0: return a1 else: return a1+1 @all_pager.setter def all_pager(self,value): print(value) @all_pager.deleter def all_pager(self): print("del all_pager") p=Foo(101) # p.all_pager #字段 # r=p.all_pager()#方法 # print(r) ret=p.all_pager print(ret) del p.all_pager
结果:
11 del all_pager
属性还有另一种存在方式
class Foo: def f1(self): return 123 def f3(self): print("del") Foo=property(fget=f1,fdel=f3) p=Foo() r=p.Foo print(r) del p.Foo
结果:
123 del
fget、fset、fdel这些名字可以随便起名,但是顺序必须要和我程序里面的顺序相同
4、成员修饰符
公有
私有:只能类本身成员内部可以访问
class Foo: def __init__(self,name): self.__name=name def __show(self): print(self.__name) @staticmethod def __ha(): print("haha") def f1(self): self.__show() def f2(self): Foo.__ha() p=Foo("wzc") p.f1() p.f2()
结果:
wzc haha
私有:__name这种就是私有,无法被外部访问,继承也无法访问,只有本身可以访问
5、特殊成员
__init__
__doc__
__call__
__str__
__dict__,获取所有字段信息,获取对象中封装的所有数据
__getitem__
__settiem__
__delitem__
等等
析构方法,在垃圾回收机制之前执行
对象后面加(),执行的是call方法
类后面加(),执行init方法
class Foo: def __init__(self,name,age): self.name=name self.age=age def __del__(self): pass def __call__(self, *args, **kwargs): print("call") def __str__(self): return "str" def __getitem__(self, item): return 123 def __setitem__(self, key, value): print("setitem") def __delitem__(self, key): print("delitem") p=Foo("wzc",18) p() print(p) print(p.__dict__) ret=p['ad'] print(ret) p['haha']=111 del p['k']
结果:
call str {'age': 18, 'name': 'wzc'} 123 setitem delitem
切片的应用
class Foo: def __getitem__(self, item): print(type(item)) return 123 def __setitem__(self, key, value): print(type(key),type(value)) def __delitem__(self, key): print(type(key)) obj=Foo() ret=obj[1:4:2] obj[1:4]=[11,22,33,44]
结果:
<class 'slice'> <class 'slice'> <class 'list'>
iter方法
class Foo: def __iter__(self): #return iter([111,11,22,33]) yield 1 yield 2 obj=Foo() for item in obj: print(item)
结果:
1 2
6、面向对象,相关联的其他边缘性的知识
--isinstance 是不是有类创建的对象
--issunclass是不是父类的子类
--继承与2.7
--应用:
自定义类型,对字典进行补充,有序字典
源码的扩展
class BAR:
def f1(self):
pass
class FOO(BAR):
def f2(self):
pass
obj=FOO()
ret=isinstance(obj,BAR)
print(ret)
r=issubclass(FOO,BAR)
print(r)
结果:
Ture
Ture
使用super来执行父类的方法
class Foo1: def f1(self): print("c1.f1") class Foo2(Foo1): def f1(self): ret=super(Foo2,self).f1() print("c2.f1") obj=Foo2() obj.f1()
结果:
c1.f1 c2.f1
c1.fi(self)也可以直接调用,但是不推荐使用
7、异常处理
try: pass except ValueError as ex: print(ex) except Exception as ex: print(ex) else: pass finally: pass
这个是一个异常处理的程序,我们会发现异常处理的执行方式是从上往下走,这也就是异常处理的捕获顺序
上面这个程序的执行顺序是:
一条线是: try==》else==》finally 另一条线: try错误==》except没生效的话==》except==》finally
try里面如果那里出错了,就会跳出执行except,后面的不会被执行
如果想要测试的话,可以使用 raise 来主动错误进行测试
8、设计模式之单例模式
可以用类方法和静态方法来实现,一般用类方法来实现
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("wzc") cls.instance=obj return obj obj1=Foo.get_instance() print(obj1) obj2=Foo.get_instance() print(obj2)
结果:
<__main__.Foo object at 0x101176be0> <__main__.Foo object at 0x101176be0>