1,类的私用属性和私用方法
类中私用属性和私用方法的使的使用是加双划线
class A: __N = 0 # 类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N def __init__(self): self.__X = 10 # 变形为self._A__X def __foo(self): # 变形为_A__foo print('from A') def bar(self): self.__foo() # 只有在类内部才可以通过__foo的形式访问到.
这样做的目的是让属性和方法不轻易的在类的外部访问,通过A._A__N 可以访问类属性。
2,类方法、静态方法
类方法是使用@classmethod来实现,作用是类方法只能访问类变量,不能访问实例变量。
静态方法使用@staticmethod来实现,作用是静态方法不能访问实例变量和类变量。
3,属性方法
属性方法是通过@property来实现的,作用是把一个方法变成静态的属性。调用的时候跟调用属性一样,不需要加()
如果需要修改属性方法进行赋值的话要重新写一个方法使用@属性方法名.setter装饰器再装饰一下。就可以对这个属性进行赋值了
删除这个方法重写一个方法使用@属性方法名.deleter,使用deleter 删除
4,反射
Python面对对象的反射是通过字符串的形式来操作对象的相关属性。
hasattr(obj,‘attr’)检测实例对象中是否包含某属性
getattr(obj,‘attr’)获取实例对象中的属性
setattr(obj,’attr‘,’value‘)设置对象中的属性值
deleattr(obj,’arrt‘) 删除实例对象中的属性值
#也可以检测当前文件中有没有某个方法和属性
def func(): print('s1') class Person(object): def __init__(self, name, age): self.name = name self.age = age name = "test" import sys this_module = sys.modules[__name__] # __name__ 会动态的代表当前模块名 print(hasattr(this_module, 'func')) print(hasattr(this_module, 'name')) print(getattr(this_module, 'Person')) p = getattr(this_module, 'Person') p("zzzz", 22)
5,类的双下划线
__len__,使用len(obj)的使用会触发这个方法
__hash__,使用hash(obj)的时候会触发到这个方法
__eq__,在比较两个对象的值是否相等的时候触发
class A: def __init__(self): self.a = 1 self.b = 2 def __eq__(self, obj): print("call eq method.") print(obj) if self.a == obj.a and self.b == obj.b: return True
item系列:
作用:是把一个对象变成dict,可以像dict一样增删改查
class Brand: def __init__(self,name): self.name=name def __getitem__(self, item): print("获取KEY",item) print(self.__dict__[item]) def __setitem__(self, key, value): print("设置一个key...",key) self.__dict__[key]=value def __delitem__(self, key): print('del obj[key]时,我执行') self.__dict__.pop(key) def __delattr__(self, item): print('del obj.key时,我执行') self.__dict__.pop(item) b=Brand('小猿圈') b["slogan"] = "自学编程谁不爱小猿圈" b["website"] = "apeland.cn" del b["website"] b['name']='小猿圈Apeland' b["name"] # 获取KEY print(b.__dict__)
__str__和__repr__
__str__是print(obj)的时候被触发
__repr__是交互式解释器中调用被触发
没有__str__方法是将会使用__repr方法,这个两个方法的返回值都必须是字符串。
__del__,当对象在内存中被释放时,自动被触发,如del obj
__new__,执行__init__方法之前需要先执行父类的__new__方法(如果本类中无__new__方法时),所以说__init__方法是__new__方法调用出来的
class Person(object): def __init__(self,name): self.name = name print("--init ....") def __new__(cls, *args, **kwargs): """ cls : 代表Person这个类本身 :param args: :param kwargs: :return: """ print("--in new: ",cls,*args,**kwargs) return object.__new__(cls) # 调用父类的__new__方法,必须这么干 ,要不然__init__方法就不会执行了 p = Person("Alex") print(p.name) print(Person)
应用场景,可以使用__new__方法实现单例模式,因为每次实例化执行__init__前都会执行__new__方法,所以用父类的__new__实例化一个对象保存到一个类变量中,当已经实例化时就不在进行实例化了。
class Printer(object): __instance = None # 用来存唯一的一个实例 __tasks = [] def __init__(self,task): self.__tasks.append(task) print("added a new task in queue..",task) def __new__(cls, *args, **kwargs): if cls.__instance is None: # 代表之前还没被实例化过 obj = object.__new__(cls) cls.__instance = obj # 把第一次实例化的对象 存下来,以后每次实例化都用这个第一次的对象 return cls.__instance # 下一次实例化时,就返回第一次实例化的对象 def jobs(self): return self.__tasks job = Printer("job1 word") job2 = Printer("job2 png") job3 = Printer("job3 excel") print(id(job),id(jo
__call__,当执行对象()或者类()()时被触发
__dict__,是用来存储对象属性的一个字典,键为属性名,值为属性名的值,如果是类属性则为空。
class Student(object): country = "china" # 类属性不会放到__dict__中 def __init__(self, name, age): self.name = name self.age = age def __str__(self): print("我是str") return "Student(%s,%d)" % (self.name, self.age) s1 = Student("JACK", 29) print(s1.__dict__) print(s1.__dict__["name"]) # JACK print(Student.__dict__)