python笔记14介绍几个魔法方法

python笔记14介绍几个魔法方法

先声明一下
各位大佬,这是我的笔记。
如有错误,恳请指正。
另外,感谢您的观看,谢谢啦!

(1).__doc__

输出对应的函数,类的说明文档

print(print.__doc__)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)

Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file:  a file-like object (stream); defaults to the current sys.stdout.
sep:   string inserted between values, default a space.
end:   string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.

自己写的也可以

class Student(object):
    '''
    类:  学生
    字段:普通:学科一成绩,学科二成绩,学科三成绩
          静态:班主任,学生信息一,学生信息二,学科一,学科二,学科三 (可更改内容)
    方法:普通:以列表形式输出各学科成绩
          静态:无
    '''
    stu_msg1 = "学号"
    stu_msg2 = "姓名"
    stu_lesson1 = "数学成绩"
    stu_lesson2 = "英语成绩"
    stu_lesson3 = "语文成绩"
    def __init__(self,nm):
        self.msg1 = nm[0]
        self.msg2 = nm[1]
        self.lesson1 = nm[2]
        self.lesson2 = nm[3]
        self.lesson3 = nm[4]
    def show_grade(self):

        return [self.msg2,self.lesson1,self.lesson2,self.lesson3]

print(Student.__doc__)

    类:  学生
    字段:普通:学科一成绩,学科二成绩,学科三成绩
          静态:班主任,学生信息一,学生信息二,学科一,学科二,学科三 (可更改内容)
    方法:普通:以列表形式输出各学科成绩
          静态:无
(2).__dict__

输出对象(或者类)的字段

当这个魔法方法前面是对象变量时,它只是输出普通字段,因为普通字段只能能被对象使用,

当魔法方法前面是类时,它会输出其他全部的字段和方法。

还是用上面我写的代码举例

ac = Student(['1024','张三','80','90','89'])
print(ac.__dict__)
print(Student.__dict__)
{'msg1': '1024', 'msg2': '张三', 'lesson1': '80', 'lesson2': '90', 'lesson3': '89'}
{'__module__': '__main__', '__doc__': '\n    类:  学生\n    字段:普通:学科一成绩,学科二成绩,学科三成绩\n          静态:班主任,学生信息一,学生信息二,学科一,学科二,学科三 (可更改内容)\n    方法:普通:以列表形式输出各学科成绩\n          静态:无\n    ', 'class_teacher': '点点', 'stu_msg1': '学号', 'stu_msg2': '姓名', 'stu_lesson1': '数学成绩', 'stu_lesson2': '英语成绩', 'stu_lesson3': '语文成绩', '__init__': <function Student.__init__ at 0x000001A22C079840>, 'show_grade': <function Student.show_grade at 0x000001A22C593D90>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>}

这里完美验证了前面学的知识,普通字段只有对象能用,

除此之外其他的静态字段,普通方法,静态方法,类方法都是共有的。

此外还要注意它返回的是一个字典

####(3).__del__以及删除机制

先讲删除机制结论;

如果在对象一直没有被调用,那么会在所有代码执行完后自动删除这个对象

如果在代码执行期间对象被你用代码删除,哪先要看这个对象是否被其他的对象引用,如果有就还是在代码执行完删除对象,如果没有则当场删除它。

__del__是在对象被删除是自动调用的函数,(由删除机制来删除,你手动写了删除代码,也是由删除机制判断到底什么时候来删除)当然,我们可以在类中重写这个函数来达到我们想要的目的

  • 声明后一直没用会在全部代码执行结束会被删除
class Student(object):
    def __del__(self):
        print("我被删除机制删除了")
ac = Student()
print('----*----')
----*----
我被删除机制删除了
  • 没被其他对象引用,又被你用代码删除,那就是当场删除
class Student(object):
    def __del__(self):
        print("我被删除机制删除了")
ac = Student()
print('----*----')
del ac
print('----*----')
----*----
我被删除机制删除了
----*----
  • 被其他对象引用,但被你用代码删除,那会是在代码全部执行结束后删除
class Student(object):
    def __del__(self):
        print("我被删除机制删除了")
ac = Student()
ac = Student()
ab = ac
print('----*----')
del ac
print('----*----')
----*----
----*----
我被删除机制删除了
(4).__call__

我们知道将类实例化后的对象变量,它里面存的是一个功能地址,而当我们不想让他返回功能地址时,我们可以用__str__魔法方法返回字符串,而我们在对象变量后面加上()想以函数形式调用这个对象,本来是会报错的 。

而用了__call__就允许这样做了,来我们来看代码。

class test:
    pass
ac = test()
print(ac)
ac()

最后一句正常是会报错的,因为是不允许这样用的

TypeError: 'Student' object is not callable
class test:
    def __call__(self, *args, **kwargs):
        print("你好")
    pass
ac = test()
print(ac)
ac()
<__main__.test object at 0x0000021C63948518>
你好

使用魔法方法后对象就变得可调用了。

(4).__new__

new方法是用来创建并返回给init一个对象

init方法是用来在对象创建时,自身初始化的

所以在实例化一个对象时 new先于init被执行

class test(object):
    def __new__(cls):
        print("--1--")
    def __init__(self):
        print('--2--')
ac = test()
--1--

这段代码为什么只执行了new,init不应当会初始化吗?

实际上,这里我们重写了new,它不再有创建对象并返回的功能,对象没有被创建自然不会去初始化

所以我们要super,object类的new

class test(object):
    def __new__(cls):
        print("--1--")
        return super().__new__(cls)
    def __init__(self):
        print('--2--')
ac = test()
--1--
--2--

我们也可以验证一下new的返回值

class test(object):
    def __new__(cls):
        print("--1--")
        d = super().__new__(cls)
        print(d)
        return d
    def __init__(self):
        print('--2--')
ac = test()
--1--
<__main__.test object at 0x0000017858EA8E48>
--2--

就是对象变量啊

(5).单例模式

在一些特定情况下,我们需要某个类只能有一个对象,比如日志记录,这就是单例模式。

class sing(object):
    __flag = 0
    def __new__(cls, *args, **kwargs):
        if cls.__flag == 0:
            cls.__flag = super().__new__(cls)
            return cls.__flag
        else:
            return cls.__flag
a = sing()
b = sing()
c = sing()
print(id(a))
print(id(b))
print(id(c))
2368668927536
2368668927536
2368668927536

可见没有新生成的对象,都是最开始哪一个

(6).反射

反射是很重要的用法,尤其是在web中,这里只是简单讲讲

我们首先建立一个模块

def find_stu():
    print('查找学生页面')
def ex_stu():
    print('修改学生页面')

将这个模块导入另一个文件中(上面的代码存在fs.py中)

import fs

正常的调用是这样的

import fs
ac = input("请选择功能:")
if ac == 'find_stu':
    fs.find_stu()
elif ac == 'ex_stu':
    fs.ex_stu()
else :
    print('未找到')
请选择功能:ex_stu
修改学生页面

接下来看点不正常的

import fs
ac = input("请选择功能:")
if hasattr(fs,ac):
    funct = getattr(fs,ac)
    funct()
else :
    print('未找到')
请选择功能:ex_stu
修改学生页面

这就是反射,很看起来一头雾水,但是也是有规律的,

hasattr,用来判断和搜素,getsttr用来获取

他们的第一个参数是要去搜索或获取的模块,第二个是对应的函数名字

如果我改一下fs里的函数的名字。它就找不到了

def find_st():
    print('查找学生页面')

stu变成st,它就找不到了

请选择功能:find_stu
未找到

这时假设我还要对其他的模块应用反射,最简单的办法是

import 新的模块,然后两个反射函数第一个参数改一下就可以了,

但是当模块非常多时哪,还一条一条加,当然不是,下面看更好的办法

再写一个模块命名为fc.py

def add_stu():
    print('添加学生页面')
def test_stu():
    print('学生成绩页面')

然后主页面这样写

ac = input("请选择路径:")
modules,func = ac.split('/')
module_now = __import__(modules)
if hasattr(module_now,func):
    funct = getattr(module_now,func)
    funct()
else :
    print('未找到')
请选择路径:fc/add_stu
添加学生页面

多试几次

请选择路径:fs/ex_stu
修改学生页面
请选择路径:fc/test_stu
学生成绩页面
请选择路径:fc/ex_stu
未找到
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值