1.今日内容
- 类的结构细分
- 私有成员*
- 类方法**
- 静态方法**
- 属性**
- isinstance issubclass
- 元类(type)与object的区别
- 异常处理***
2.具体内容
-
类大致分为两块区域
- 静态字段
- 私有静态变量
- 方法部分
- 特殊方法(如
__init__
)- 对象属性(普通字段)
- 私有对象属性(私有普通字段)
- 普通方法
- 私有方法(def __func())
- 类方法(@classmethod)
- 静态方法(@staticmethod)
- 属性(@property)
- 特殊方法(如
- 静态字段
-
私有成员*(私有类的静态属性,私有对象属性,私有方法)
- 类、对象的私有静态属性或方法:在类外部不能被访问的属性或方法
class B: school_name = '浙大' __major = '计算机' def __init__(self,weight): self.weight = weight class A(B): class_name = '一班' __girlnum = '1个' def __init__(self,name,age,weight): self.name = name self.__age = age super().__init__(weight) def func(self): print(self.__major) #baocuo print(self.__girlnum) obj = A() print(obj.__girlnum) #baocuo print(A.__girlnum) #baocuo obj.func()
-
Remark:
- 类内部可以访问,类外部,派生类不能访问
- 私有属性的用途:运行至一些加密用途的变量
- python中的私有变量的访问权限并不像C++那般严格,强行访问也是可以的(利用类空间字典):
class A: __girlnum = '1个' print(A.__dict__) print(A._A__girlnum)
-
类方法**
- 由类名直接调用的方法,自动将类名传给cls,由一个装饰器classmethod引导:
class A: num = 1 def func(self): print('方法') @classmethod def a_func(cls): print(cls) print(cls.num) obj = A() A.a_func() obj.a_func()#对象也可以调用类方法,但是会自动将其从属于的类名传递给cls
class Student: num = 0 def __init__(self,name): self.name = name self.count() @classmethod def count(cls): cls.num += 1 @classmethod def get_num(cls): return cls.num Student.count() print(Student.get_num())#1 a = Student('ll') print(a1.get_num())#2
- Remark:
- 类方法直接将被装饰的方法中的第一个行参,由self替换成cls,cls传的是类名
- 对象也可以调用类方法,但会将其从属的类名,传给cls
-
静态方法**
- 在类中不依赖类于对象的方法,由装饰器staticmethod引导:
class A: def func(self): print(111) @classmethod def a_func(cls): print(cls) @staticmethod def static_func(a,b,c): print(f'{a}{b}{c}静态方法') obj = A() obj.static_func(1,2,3)#123静态方法
- Remark:
- 被装饰的静态方法中,方法的第一个行参不会被默认为self,因此,实质上等同于一个类外的普通函数
- 静态方法放置于类中的原因是:使程序的结构更加清晰于合理
-
属性**
- 方法伪装成属性:使程序更加友好于合理化,由装饰器property引导:
class Bmi: def __init__(self,name,weight,height): self.name = name self.age = age self.height = height @property def bmi(self): return self.weight / self.height**2 tb = Bmi('ddd',55,1.55) print(rb.bmi)#22.892819979188342
-
Remark:
- 代码本质上没有提升,只是看起来更规范化
- 伪装成’属性‘可以被修改(增删改),但不是真正意义上的修改,而是遇到增删改命令时,执行另一个方法,同样由装饰器引导:
class Foo: def __init__(self,name): self.name = name @property def aaa(self): print('get的时候运行') @aaa.setter def aaa(self,v): print('修改的时候执行') @aaa.deleter def aaa(self): print('删除的时候执行') obj = Foo('小白') print(obj.name) obj.aaa obj.aaa = 'ddd' del obj.aaa #小白 #get的时候运行 #修改的时候执行 #删除的时候执行
- 对于属性修改的另一种方法(运行property()类的实例化):
class Foo: def get_AAA(self): print('get的时候运行') def set_AAA(self,v): print('set的时候运行') def delete_AAA(self): print('delete的时候运行') bbb = property(get_AAA,set_AAA,delete_AAA) f1 = Foo() f1.bbb f1.bbb = 'sss' del f1.bbb #get的时候运行 #set的时候运行 #delete的时候运行
-
isinstance issubclass
- 对象与类的关系
- isinstance(obj,N) ,判断obj对象是由N类(N的派生类)实例化的对象,返回True
- 类与类之间的关系
- issubclass(M,N):判断M类是N类的子孙
class A: pass class B(A): pass class C(B): pass obj = B() print(isinstance(obj,B))#True print(isinstance(obj,A))#True print(isinstance(obj,C))#False print(issubclass(C,B))#True print(issubclass(C,A))#True
- 对象与类的关系
-
元类(type)与object的区别
- type():从类的角度看type(),它是一个元类,即所有的类均是这个类的一个实例化
- object类是type类的一个实例化,同时,type类是object类的一个子类
-
异常处理***
-
异常:程序出现中断与报错,分为两种:
- 语法错误:所写代码不符合python开发规范
- 逻辑错误:所写代码的执行结果与开发着需求不符
-
异常处理:就是排错
- 用if进行异常处理
num = input('请输入:') if num.isdecimal(): num = int(num) if 0<num<6: pass elif num = 10: pass else: print('由错误')
- 用try-except进行异常处理
dic = {1:111,2:222,3:333} while 1: try: num = input('请输入序号') int(num) print(dic[int(num)]) except KeyError as e: print('选项超出范围,请重新输入') except ValueError as e: print('请输入数字') except Exception: pass finally: print('执行finally')
-
Remark:
-
Except:可以使用多次,做到逐一处理异常,用于出现某错误而产生提示
-
Exception:万能异常,包含所有异常信息,用于批量出现错误
-
finally:在程序报错之前的最后一刻执行finally代码;但在正常操作时,依然会执行此代码。用于文件操作与连接数据库操作
-
raise:主动抛出异常
-
assert:断言,条件成立会继续执行,不成立将会报错:
assert 1=1: print(111) assert 1=2: print(222)
-
异常处理需慎用,因为其消耗性能,过多使用异常会导致代码可读性变差,需要在关键节点使用。
-
-