目录
类方法@classmethod
静态方法@staticmethod
属性方法@property
__name__
反射
hasattr
getattr
setattr
delattr
动态加载模块
类的双下划线方法
将对象当成字典写法的魔法方法
str & repr
new方法
call方法
动态创建类
创建错误类
类方法通过@classmethod装饰器实现,其只能访问类变量,不能访问实例变量
class dog:
name=1
def __init__(self,name):
self.name=name
def func1(self):
print(self)
@classmethod
def func2(self):
print(self)
print(self.name)
p1=dog(2)
p1.func1()
p1.func2()
# <__main__.dog object at 0x00000241F0A03400>
#
# 1
可以看出类方法的self这个参数接受的不是实例本身,而是类本身,所以不能访问实例变量
这里举例一个使用场景,每次实例化一次就计数一次(这个地方不能把__num+=1放在初始化函数中,因为那样相当于创建了一个新的实例变量)
class person:
__num=0
def __init__(self):
self.__add()
@classmethod
def __add(cls):
cls.__num+=1
print(cls.__num)
p1=person()
p2=person()
静态方法通过@staticmethod装饰器实现,其不能访问类变量,不能访问实例变量
静态方法隔断了其跟类和实例的任何关系
class person:
__num=0
def __init__(self,name):
self.name=name
@staticmethod
def test(obj):
print(obj.name)
p1=person('lee')
p1.test(p1)
在调用时,他无法获取self参数,只能自己手动传入
把一个方法变成一个静态的属性
调用时不要加()
class person:
def __init__(self,name):
self.name=name
@property
def test(obj):
print(obj.name)
p1=person('lee')
p1.test
# lee
这里的应用场景是,根据对象内部的属性进行某些操作,而不需要传入参数的过程
Python @property属性详解 - 知乎
在当前模块主动执行的情况下(不是被导入执行),等于__main__
在被其它模块导入执行的情况下,等于模块名
反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。
说白了就是可以通过字符串的形式来操作对象的属性
查询类或对象是否含有方法或者属性
class person:
num=1
def __init__(self,name,age):
self.name=name
self.age=age
def walk(self):
print(111)
p=person('lee',21)
print(hasattr(person,'num'),hasattr(person,'walk'))
# True True
print(hasattr(p,'name'),hasattr(p,'age'))
# True True
获取类或对象的方法或者属性的值
class person:
num=1
def __init__(self,name,age):
self.name=name
self.age=age
def walk(self):
print(111)
p=person('lee',21)
print(getattr(p,'name'))
# lee
print(getattr(person,'num'))
# 1
给类或对象的方法或者属性赋值
class person:
num=1
def __init__(self,name,age):
self.name=name
self.age=age
def walk(self):
print(111)
def talk(self):
print(22222)
p=person('lee',21)
setattr(p,'name','liu')
print(p.name)
setattr(person,'talk',talk)
p.talk()
# liu
# 22222
删除类或对象的方法或属性
delattr(person,'num')
可以在后期使用字符串动态的导入新的模块
方法一
__import__('model_name')
方法二
import importlib
importlib.import_module('model_name')
全部内容可以看这个
python魔法方法长文详解 - 个人文章 - SegmentFault 思否
这里挑几个重要的写一下
__getitem__ :以字典的形式获取值,当使用 obj['key']的时候就会使用这个方法
__setitem__:以字典的形式设置值,当使用 obj['key']=value时就会调用这个方法
__delitem__,__delattr__:都是删除,只是调用形式不一样
class person:
num=1
def __init__(self,name,age):
self.name=name
self.age=age
def __getitem__(self, item):
return self.__dict__[item]
def __setitem__(self, key, value):
self.__dict__[key]=value
def __delitem__(self, key):
self.__dict__.pop(key)
print(1111)
def __delattr__(self, item):
self.__dict__.pop(item)
print(2222)
p=person('lee',12)
print(p['name'])
p['age']=2
del p['name']
del p.age
# lee
# 1111
# 2222
当什么都不设置时
class person:
num=1
def __init__(self,name,age):
self.name=name
self.age=age
p=person('lee',12)
print(p)
print(str(p))
print(repr(p))
# <__main__.person object at 0x0000022CBB838668>
# <__main__.person object at 0x0000022CBB838668>
# <__main__.person object at 0x0000022CBB838668>
如果定义了__str__() 函数:
class person:
num=1
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return '11111'
p=person('lee',12)
print(p)
print(str(p))
print(repr(p))
# 11111
# 11111
# <__main__.person object at 0x0000019AF5038828>
new方法负责执行__init__,是执行在__init__方法前的
class person(object):
num=1
def __init__(self,name,age):
self.name=name
self.age=age
print(1111)
def __new__(cls, *args, **kwargs):
print(cls,*args, **kwargs)
p=person('lee',12)
# lee 12
上面这种写法重写了 new方法,所以__init__就没有被调用了
正确一般是:
class person(object):
num=1
def __init__(self,name,age):
self.name=name
self.age=age
print(1111)
def __new__(cls, *args, **kwargs):
print(cls,*args, **kwargs)
return object.__new__(cls)
p=person('lee',12)
# lee 12
# 1111
这里举一个实例,即单例模式,其实就是当创造了实例时,后面再尝试创造实例将会失败并直接返回第一次创造的实例
class person(object):
num=0
objfirst=None
def __init__(self,name,age):
self.name=name
self.age=age
def __new__(cls, *args, **kwargs):
if cls.num==0:
cls.objfirst=object.__new__(cls)
cls.num+=1
return cls.objfirst
else:
return cls.objfirst
p1=person('lee',11)
p2=person('liu',33)
print(p1)
print(p2)
# <__main__.person object at 0x00000127C5FCC128>
# <__main__.person object at 0x00000127C5FCC128>
实例名()就执行这个方法
class person(object):
num=0
objfirst=None
def __init__(self,name,age):
self.name=name
self.age=age
def __call__(self, *args, **kwargs):
print(1111)
p1=person('lee',12)
p1()
# 1111
python中的可以使用type()函数动态的创建一个类
type('类名',(继承的类,),{属性名:值,方法名:方法})
def __init__(self,name,age):
self.name=name
self.age=age
def talk(self):
print(1111)
person = type('person',(object,),{'num':1,'__init__':__init__,'talk':talk})
p1=person('lee',21)
print(p1.name)
p1.talk()
# lee
# 1111
python可以自己定义错误类,继承baseException的基类
class MyError(BaseException):
def __init__(self,msg):
self.msg=msg
def __str__(self):
return self.msg
try:
raise MyError('my error')
except MyError as e:
print(22222,e)
# 22222 my error