首页 > 代码库 > Python 面向对象
Python 面向对象
方法:所有的方法是属于类的
1、普通方法:至少一个self,对象执行
2、静态方法:任意参数,类执行
3、类方法:至少一个cls,类执行
类方法:
在Python的面向对象方法中,支持3种,一种是普通方法,静态方法,类方法
类方式其实是静态方法的一种特殊形式:
class Foo: def __int__(self, name): self.name = name # 类方法是静态方法一种,由类来调用 @classmethod def f2(cls): # 必须至少要有一个参数cls print(cls) f = Foo() f.f2() # 不用添加参数,自动把类名传入cls参数
cls是类名,如果加上()就是创建对象
属性
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 + 1 p = Pager(101) ret = p.all_pager print(ret)
属性就是通过是用调用字段的方式调用类里面的方法(去掉括号),其它功能跟调用方法一致,在写代码的时候可能比较好看。
但是问题来了,字段可以进行赋值,你这个可以吗?
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 + 1 p = Pager(101) p.all_pager = 10 # 输出 Traceback (most recent call last): File "D:/oop2.py", line 26, in <module> p.all_pager = 10 AttributeError: can‘t set attribute
比如我想对p.all_pager重新赋值为10,那程序肯定报错。
那可以设置吗?
答案是:肯定可以,如果你想设置需要在类里面创建一个方法,并在方法上加上一个装饰器@[方法名字].setter
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 + 1 @all_pager.setter def all_pager(self, value): print(value) p = Pager(101) p.all_pager = 10 # 输出 10
上面我们介绍了,可以获取,可以设置,还缺少一个可以删除,那下面我们来实现删除
实现删除其实跟实现设置一样,需要在类里面定义一个方法并在方法上加上@[方法名字].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 + 1 @all_pager.setter def all_pager(self, value): print(value) @all_pager.deleter def all_pager(self): print(‘del all_pager‘) p = Pager(101) del p.all_pager
到此为止,属性伪造成字段的访问方式后,完全可以进行输出、设置、及删除了
类继承-重构子类使用super的初始化方法
class Member(object): def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex class Student(Member): def __init__(self, name, age, sex, sid): super(Student, self).__init__(name, age, sex) self.sid = sid def info(self): info = ‘‘‘ 学生名称:{name} 学生年龄:{age} 学生性别:{sex} 学生编号:{sid} ‘‘‘.format(name=self.name, age=self.age, sex=self.sex, sid=self.sid) print(info) class Teacher(Member): def __init__(self, name, age, sex, tid, salary): super(Teacher, self).__init__(name, age, sex) self.tid = tid self.salary = salary def info(self): info = ‘‘‘ 老师名称:{name} 老师年龄:{age} 老师性别:{sex} 老师编号:{sid} 老师工资:{salary} ‘‘‘.format(name=self.name, age=self.age, sex=self.sex, sid=self.tid, salary=self.salary) print(info) s1 = Student(‘Tom‘, 18, ‘男‘, ‘S0001‘) s1.info() t1 = Teacher(‘jerry‘, 28, ‘男‘, ‘T0001‘, 0) t1.info()
类的多继承,适用于python 3.x
class C_2: def f2(self): print(‘C-2‘) class C_1(C_2): def f2(self): print(‘C-1‘) class C0(C_2): def f1(self): print(‘C0‘) class C1(C0): def f1(self): pass class C2(C_1): def f2(self): print(‘c2‘) class C3(C1, C2): def f3(self): pass obj = C3() obj.f2()
总结:
当没有共同的父类的时候,深度优先,当有共同父类的时候广度优先
类的魔术方法
Python在类中存在一些特殊方法,被称为"魔术方法",下面我们来见识一下:
1、__init__ 重要程度: *****
按照字面的意思其实就是初始化,它在类中有什么用呢?相信学习面向对象的人第一个接触的就是它了,我的理解是:在实例化对象的时候被自动触发并执行
class Foo: def __init__(self, name, age): self.Name = name self.Age = age print(‘我开始执行了‘) f = Foo(‘chen‘, 20) # 输出 我开始执行了
通过例子可以看出,我只是实例化了类,没有进行任何动作,就打印出来了
2、__dict__ 重要程度: ***
用于储存类或实例的属性,当使用类+__dict__打印类的属性,使用实例+__dict__打印实例的属性
class Foo: country = ‘CN‘ def __init__(self, name, age): self.Name = name self.Age = age f = Foo(‘chen‘, 20) print(f.__dict__) # 以字典形式显示实例的属性 print(Foo.__dict__) # 以字典形式显示类的属性 # output {‘Name‘: ‘chen‘, ‘Age‘: 20} {‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Foo‘ objects>, ‘__doc__‘: None, ‘__module__‘: ‘__main__‘, ‘country‘: ‘CN‘, ‘__init__‘: <function Foo.__init__ at 0x000000000377BA60>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘Foo‘ objects>}
3、__doc__ 描述类的信息 重要程度: ***
class Foo: """ 这是一个显示doc的类的例子 """ def __init__(self): pass print(Foo.__doc__) # 输出 这是一个显示doc的类的例子
4、__call__ 重要程度: *****
在对象后边加(),触发__call__方法
class Foo: def __call__(self, *args, **kwargs): print(‘调用我吧‘) f = Foo() f()
5、__del__ : 析构方法 重要程度: *
在垃圾回收前执行它,貌似没啥用
6、__class__ 和__module__ 重要程度: *
class Foo: def __init__(self): pass f = Foo() print(f.__class__) print(f.__module__) # 输出 <class ‘__main__.Foo‘> __main__
7、__str__
使用这个方式打印f对象输出的是对象,那能否输出内容呢?答案是肯定的,使用__str__
class Foo: def __init__(self, name, age): self.name = name self.age = age f = Foo(‘tom‘, 11) print(f) # 输出 <__main__.Foo object at 0x000000000337B278>
修改一下代码:这样你在打印对象的时候就可以看见被封装的数据了
class Foo: def __init__(self, name, age): self.name = name self.age = age def __str__(self): return ‘{name}--{age}‘.format(name=self.name, age=self.age) f = Foo(‘tom‘, 11) print(f) # 输出 tom--11
7、__add__
8、__getitem__、__setitem__、__delitem__ 重要程度: *****
搞清楚__getitem__之前,我们先看看字典的实现方法:
dic = {‘k1‘:‘v1‘} 等同于 dic = dict(k1=v1)
当我们取值的时候,可以
dic[‘k1‘] 那这个怎么实现呢?
只要在对象+[]中括号就是调用__getitem__方法
class Foo: def __getitem__(self, item): print(item) f = Foo() f[‘abcd‘] # 输出 abcd
class Foo: def __setitem__(self, key, value): print(key, value) f = Foo() f[‘k1‘] = 123
class Foo: def __delitem__(self, key): print(key) f = Foo() del f[‘k1‘]
利用上述模块,做一个有序字典,转自武sir
class MyDict(dict): def __init__(self): super(MyDict, self).__init__() self.li = [] def __setitem__(self, key, value): self.li.append(key) super(MyDict, self).__setitem__(key, value) def __str__(self): tmp_list = [] for key in self.li: value = self.get(key) tmp_list.append("‘%s‘:%s" % (key, value)) temp_str = ‘{‘ + ‘,‘.join(tmp_list) + ‘}‘ return temp_str obj = MyDict() obj[‘k1‘] = 123 obj[‘k2‘] = 123 print(obj)
9、__iter__
默认对象是不可迭代的
异常处理
完整代码块:
try: # 逻辑代码放这里 pass except IndexError as e: # 当逻辑处理块出现错误后,顺序查看错误原因,如果为IndexError这个块先进行处理,否则执行下边的except Exception语句 print(e) # str except Exception as e: print(e) else: # 逻辑处理块未出现异常,执行这里代码 pass finally: # 释放资源 # 不管你上边是否出现错误,本块永远执行,在逻辑处理块执行完毕后。 pass
Python 面向对象