Python面向对象编程(二)类方法、静态方法、属性方法、__name__、反射、双下划线方法、动态创建类、创建自定义错误类等

目录

类方法@classmethod

静态方法@staticmethod

属性方法@property

name

反射

hasattr

getattr

setattr

delattr

动态加载模块

类的双下划线方法

将对象当成字典写法的魔法方法

[str & repr](#str & repr)

new方法

call方法

动态创建类

创建错误类


类方法**@classmethod**

类方法通过**@classmethod**装饰器实现,其只能访问类变量,不能访问实例变量

python 复制代码
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>
# <class '__main__.dog'>
# 1

可以看出类方法的self这个参数接受的不是实例本身,而是类本身,所以不能访问实例变量

这里举例一个使用场景,每次实例化一次就计数一次(这个地方不能把__num+=1放在初始化函数中,因为那样相当于创建了一个新的实例变量)

python 复制代码
class person:
    __num=0
    def __init__(self):
        self.__add()
    @classmethod
    def __add(cls):
        cls.__num+=1
        print(cls.__num)


p1=person()
p2=person()

静态方法**@staticmethod**

静态方法通过**@staticmethod**装饰器实现,其不能访问类变量,不能访问实例变量

静态方法隔断了其跟类和实例的任何关系

python 复制代码
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参数,只能自己手动传入

属性方法@property

把一个方法变成一个静态的属性

调用时不要加()

python 复制代码
class person:
    def __init__(self,name):
        self.name=name
    @property
    def test(obj):
        print(obj.name)

p1=person('lee')
p1.test
# lee

这里的应用场景是,根据对象内部的属性进行某些操作,而不需要传入参数的过程

Python @property属性详解 - 知乎

name

在当前模块主动执行的情况下(不是被导入执行),等于**main**

在被其它模块导入执行的情况下,等于模块名

反射

反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。

说白了就是可以通过字符串的形式来操作对象的属性

hasattr

查询类或对象是否含有方法或者属性

python 复制代码
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

getattr

获取类或对象的方法或者属性的值

python 复制代码
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

setattr

给类或对象的方法或者属性赋值

python 复制代码
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

删除类或对象的方法或属性

python 复制代码
delattr(person,'num')

动态加载模块

可以在后期使用字符串动态的导入新的模块

方法一

python 复制代码
__import__('model_name')

方法二

python 复制代码
import importlib
importlib.import_module('model_name')

类的双下划线方法

全部内容可以看这个

python魔法方法长文详解 - 个人文章 - SegmentFault 思否

这里挑几个重要的写一下

将对象当成字典写法的魔法方法

getitem:以字典的形式获取值,当使用 obj['key']的时候就会使用这个方法

setitem:以字典的形式设置值,当使用 obj['key']=value时就会调用这个方法

delitem,delattr:都是删除,只是调用形式不一样

python 复制代码
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

str & repr

当什么都不设置时

python 复制代码
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__() 函数:

python 复制代码
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>
  • str函数或者print函数调用时--->obj._str()
  • repr或者交互式解释器中调用时--->obj.repr_()
  • 如果_str__没有被定义,那么就会使用_repr___来代替输出
  • 注意:这俩方法的返回值必须是字符串,否则抛出异常

new方法

new方法负责执行__init__,是执行在__init__方法前的

python 复制代码
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)
# <class '__main__.person'> lee 12

上面这种写法重写了 new方法,所以__init__就没有被调用了

正确一般是:

python 复制代码
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)
# <class '__main__.person'> lee 12
# 1111

这里举一个实例,即单例模式,其实就是当创造了实例时,后面再尝试创造实例将会失败并直接返回第一次创造的实例

python 复制代码
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>

call方法

实例名()就执行这个方法

python 复制代码
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()函数动态的创建一个类

python 复制代码
type('类名',(继承的类,),{属性名:值,方法名:方法})
python 复制代码
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的基类

python 复制代码
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
相关推荐
数据智能老司机8 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机9 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机9 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机9 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i9 小时前
drf初步梳理
python·django
每日AI新事件9 小时前
python的异步函数
python
这里有鱼汤10 小时前
miniQMT下载历史行情数据太慢怎么办?一招提速10倍!
前端·python
databook19 小时前
Manim实现脉冲闪烁特效
后端·python·动效
程序设计实验室19 小时前
2025年了,在 Django 之外,Python Web 框架还能怎么选?
python
倔强青铜三21 小时前
苦练Python第46天:文件写入与上下文管理器
人工智能·python·面试