私有成员只是做了一个简单是变相加密,直接访问不了
在变量名前加 __ 可以在本类的内部访问,在类的外部和派生类中无法访问
class A: country = ‘中国‘ __country = ‘加拿大‘ # 私有静态属性 def func(self): print(A.country) print(A.__country) class B(A): def func1(self): print(super().country) obj = A() # 在类的内部访问: 可以 obj.func() # 类的外部访问: 不可以 print(A.__country) obj.__country # 在派生类访问: 不可以 obj1 = B() obj1.func1()
可以在本类的内部访问,在类的外部和派生类中无法访问
class A: def __f1(self): print(‘in A f1‘) def func(self): self.__f1() class B(A): def f1(self): super().__f1() obj = A() # 类内部可以访问 obj.func() # 类外部不可以访问 obj.__f1() # 类的派生类: 不可以访问 b = B() b.f1()
class A: def __init__(self,name,age): self.name = name self.__age = age def func(self): print(self.__age) obj = A(‘静哥‘,24) #类内部可以访问: obj.func() #类的外部不能访问: print(obj.__age) #派生类也不能访问
什么时候使用私有成员:
密码,年龄,个人信息,只是类内部使用的方法等,需要设置私有成员
通过类名调用的方法,第一个参数主动接收类名,为了区分,参数名为cls
对象也可以调用类方法,传给cls的参数也是类空间(一般不这么用)
主动接收类名,与类的静态属性相关的需求,与对象无关的功能需要类方法
class Student: stu_num = 0 def __init__(self,name,age): self.name = name self.__age = age Student.calc_num() # 应该放在__new__里面 @classmethod def calc_num(cls): cls.stu_num += 1 @classmethod def get_num(cls): return cls.stu_num denge = Student(‘邓哥‘,18) jinge = Student(‘静哥‘,18) print(Student.get_num()) 结果: 2
不依赖与类以及对象的方法,是函数
静态方法虽然不依赖与对象,类,但是为了保持代码的整体性和一致性,才将其设置为静态方法,而不是放在类外面当普通函数用
class A: def __init__(self,name,age): # 双下方法 特殊方法 self.name = name self.__age = age def func(self): # 实例方法:通常是通过对象去调用的方法,主动将对象传给self print(‘in func‘) @classmethod def func1(cls): # 类方法: 是通过类名调用的方法,第一个参数主动接受类名 print(‘类方法‘) @staticmethod # 静态方法:不依赖于类以及对象的方法,是函数. def func2(): pass
将方法伪装成属性,虽然在代码逻辑上没有提升,但是看起来更合理
class Bmi: def __init__(self,name,weight,height): self.name = name self.__weight = weight self.height = height @property def bmi(self): return self.__weight/(self.height**2) obj = Bmi(‘hu‘,75,1.75) print(obj.bmi) #bmi本身是一个方法,通过@property装饰器之后,直接用调用属性的方式进行打印就可以
另外有更改和删除的方法:
class A: @property def AAA(self): print(‘调用属性‘) @AAA.setter def AAA(self,new): #更改属性时要传参 print(‘更改属性‘) @AAA.deleter def AAA(self): print(‘删除属性‘) obj = A() # obj.AAA #调用 # obj.AAA = 111 #更改 # del obj.AAA #删除
####练习: class Goods: def __init__(self,name,money,sale): self.name = name self.money = money self.sale = sale @property def price(self): return self.money*self.sale @price.setter def price(self,new): self.money = new / self.sale apple = Goods(‘苹果‘,5,0.9) #计算现价 # print(apple.price) #要求改过之后的价格为10 apple.price = 10 print(apple.price)
源码见的最多的是 property
对象自己的属性 如果与类的伪装的属性重名时,对对象属性进行修改时,则只会执行@setter方法
为了避免这个坑,给对象设置的属性名,不要与property伪装的属性名重名
isinstance(o,a) 判断o是否是a或者a的派生类的对象
class A: pass class B(A): pass obj = B() print(isinstance(obj,B)) #True print(isinstance(obj,A)) #True
issubclass(a,b) 判断a是否是b的子类或孙类
class A: pass class B(A): pass class C(B): pass print(issubclass(B,A)) #True print(issubclass(C,A)) #True
list str等这些可迭代对象与 Iterable是什么关系?
from collections import Iterable l1 = [1,2,3] print(isinstance(l1,Iterable)) # l1是Iterable(派生类)的实例的对象
list类与Iterable类是什么关系?
print(issubclass(list,Iterable)) # list是Iterable的派生类
python 一切皆对象原则
类也是对象
type 元类,也叫构建类,产出了python中大量的内置类(str,list...)以及自建类
通过字符串对对象进行相应的操作(对象:实例化对象 类 其他模块 本模块)
hasattr() 判断有没有
getattr() 取值
setattr() 设置(增)
delattr() 删除
class A: country = ‘中国‘ def __init__(self,name,age): self.name = name self.age = age def func(self): print(‘in A func‘) obj = A(‘棍哥‘,20) print(hasattr(obj,‘name‘)) #判断有没有‘name‘属性 print(getattr(obj,‘name‘)) #取‘name‘的值 setattr(obj,‘height‘,180) #增加‘height‘ print(obj.__dict__) delattr(obj,‘age‘) #删除‘age‘ print(obj.__dict__)
注意事项:
反射只能用在都可以通过 . 去操作的对象
class User: def login(self): print(‘欢迎来到登录页面‘) def register(self): print(‘欢迎来到注册页面‘) def save(self): print(‘欢迎来到存储页面‘) while 1: choose = input(‘请输入‘).strip() obj = User() if hasattr(obj,choose): getattr(obj,choose)()
判断函数与方法:
def func(): pass class A: def func1(self): pass #1.通过打印名字的方式判断 print(func) #函数 print(A.func1) #函数 obj = A() print(obj.func1) #方法 #2.通过引用模块 from types import FunctionType 函数 from types import Methodtype 方法 print(isinstance(func,FunctionType)) # True print(isinstance(A.func1,FunctionType)) # True print(isinstance(obj.func1,FunctionType)) # Flase print(isinstance(obj.func1,MethodType)) # True
之前学的函数就是函数
通过类名调用,就是函数
通过实例调用,就是方法
类中的静态方法是函数
类中的类方法,是方法
函数与方法的区别:
函数是显性传参,不依赖于对象
方法是隐形传参(默认接收对象空间或者类空间),依赖对象,类
解释器提供的,由__方法名__的具有特殊意义的方法,主要是python源码程序员使用的元编程,开发中尽量不使用
__init__ 类名()触发
1)len ****
一个实例能否使用len操作,完全取决于它的类中有没有__len__方法
class A: def __init__(self,name,age,sex,weight): self.name = name self.age = age self.sex = sex self.weight = weight def __len__(self): print(666) return len(self.__dict__) obj = A(‘刘姐‘,18, ‘女‘,100) len(obj) # 只要对对象len() 就会触发对象从属于的类中的 __len__ print(len(obj))
结果:
666
666
4
2)__hash__
class A: def __init__(self): pass def __hash__(self): return 666 obj = A() print(hash(obj)) #触发__hash__方法
3)__str__
class A: def __init__(self,name,age): self.name = name self.age = age def __str__(self): return str(self.__dict__) obj = A(‘alex‘,73) print(obj) 结果: {‘name‘: ‘alex‘, ‘age‘: 73}
4)__repr__
class A: def __repr__(self): return ‘alex‘ obj = A() print(repr(obj)) 结果: alex
5)_call__: 对象() 执行 __call__方法 *****
class A: def __init__(self): print(111) def __call__(self, *args, **kwargs): print(666) obj = A() #触发__init__方法 obj() #触发__call__方法
6)__eq__
class A: def __init__(self): self.a = 1 self.b = 2 def __eq__(self,obj): print(666) a = A() b = A() print(a == b) # 同一个类的两个实例进行比较就会触发类中 __eq__方法 结果: 666 None
6)__del__ 析构方法
class A: def __del__(self): print(666) obj = A() 结果: 666
7)__new__ 构造方法 ***
类名() 调用__new__方法
class A: def __init__(self,name,age): self.name = name self.age = age print(111) def __new__(cls, *args, **kwargs): print(222) return object.__new__(cls) obj = A(‘barry‘,18) 结果: 222 111
单例模式 规定一个类只能实例化一个对象(面试题)
class A: pass ret = A() print(ret) ret = A() print(ret) ret = A() print(ret) #以上三个ret内存地址是不同的
class A: __instance = None def __new__(cls, *args, **kwargs): if not cls.__instance: obj = object.__new__(cls) cls.__instance = obj return cls.__instance ret = A() print(ret) ret = A() print(ret) ret = A() print(ret) #以上三个ret内存地址是一样的
8)__item__: *****
对对象进行类似于字典的操作的时候,就会触发相应的方法.
class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): return self.__dict__[item] def __setitem__(self, key, value): # print(key,value) self.__dict__[key]=value def __delitem__(self, key): print(key) print(‘del obj[key]时,我执行‘) self.__dict__.pop(key) def __delattr__(self, item): print(‘del obj.key时,我执行‘) self.__dict__.pop(item) f = Foo(‘alexsb‘) print(f[‘name‘]) print(f.__dict__) f[‘name‘] = ‘sb‘ # 触发 __setitem__方法 print(f.__dict__) del f[‘name‘] 结果: alexsb {‘name‘: ‘alexsb‘} {‘name‘: ‘sb‘} name del obj[key]时,我执行
9)上下文管理
class A: def __init__(self, text): self.text = text def __enter__(self): # 开启上下文管理器对象时触发此方法 self.text = self.text + ‘您来啦‘ return self # 将实例化的对象返回f1 def __exit__(self, exc_type, exc_val, exc_tb): # 执行完上下文管理器对象f1时触发此方法 self.text = self.text + ‘这就走啦‘ f1 = A(‘大爷‘) # print(f1.text) with A(‘大爷‘) as f1: print(f1.text) print(f1.text) 结果: 大爷您来啦 大爷您来啦这就走啦
原文:https://www.cnblogs.com/sandy-123/p/10370283.html