面向对象进阶---魔术方法

内置方法 双下方法 魔术方法:  都是python的对象内部自带的  并且都不需要我们自己去调用它

1.  __str__  __repr__:改变对象的字符串显示   输出的类型为str

class Course:
    def __init__(self, name, price, period):
        self.name = name
        self.price = price
        self.period = period

    def __repr__(self):  # 备胎
        return ‘%s,%s,%s‘ % (self.name, self.price, self.period)    #return 类型必须是str

    def __str__(self):
        return self.name      #return的类型必须是str

python = Course(‘python‘, 25000, ‘6 months‘)
print(python)               #-->python
print(‘course %s‘ % python) #-->course python

print(repr(python))         #-->python,25000,6 months
print(‘course %r‘ % python) #-->course python,25000,6 months

  总结:   

  如果__str__存在,__repr__也存在    那么print(obj)和使用字符串格式化format,%s这两种方式 调用的都是__str__    而repr(obj)和%r格式化字符串,都会调用__repr__  如果str不存在,repr存在    那么print(obj),字符串格式化format,%s,%r 和repr(obj)都调用__repr__  如果str存在,repr不存在    那么print(obj)和使用字符串格式化format,%s这两种方式 调用的都是__str__    repr(obj)和%r格式化字符串 都会打印出内存地址
class Course(object):
    def __init__(self,name,price,period):
        self.name = name
        self.price = price
        self.period = period

    def __repr__(self):   # 备胎
        return ‘%s,%s,%s‘%(self.name,self.price,self.period)      #return类型必须是str

    def __str__(self):
        return self.name      #return类型必须是str

class Python(Course):
    pass
    def __repr__(self):   # 备胎
        return ‘%s--%s--%s‘%(self.name,self.price,self.period)

    # def __str__(self):
    #     return ‘全栈开发 :‘+self.name

py20 = Python(‘python‘,25000,‘6 months‘)
print(py20)
# 打印对象 先走自己的__str__,如果没有,走父类的,如果除了object之外的所有父类都没有str# 再回来,找自己的__repr__,如果自己没有,再找父类的,如果父类也没有,就打印内存地址
repr是str的备胎和所有的字符串格式化以及直接打印这个对象相关 推荐使用repr
2. __new__ 构造方法  生产对象的时候用的 - 单例模式
  实例化一个Foo的对象  先开辟一块儿空间,使用的是Foo这个类内部的__new__  如果我们的Foo类中是没有__new__方法的,则调用object类的__new__方法


class Foo:
    def __new__(cls, *args, **kwargs):   #cls永远不会使用self参数,因为self 是这之后才被创建出来的
        print(‘in new‘)  # 先执行  
        obj = object.__new__(cls)      #self空间在这一步才创建出来
        print(obj)  
        return obj               #将创建出来的空间返回给self 

    def __init__(self):
        print(‘init‘)
        print(self)  # 后执行    
Foo()
‘‘‘
in new
<__main__.Foo object at 0x000001D5A4A27400>    
init
<__main__.Foo object at 0x000001D5A4A27400>  obj和self内存地址一样
‘‘‘
 单例模式:
    一个类有且只能有一个实例:可以被实例化多次 但是保留最后一次实例化的属性
 
#单例模式
class A:
    __flag = None          #创建一个静态变量来指向同一内存空间
    def __new__(cls, *args, **kwargs):
        if cls.__flag is None:    #首次没有内存空间就创建一个新的  如果有就不在创建
            cls.__flag = object.__new__(cls)
        return cls.__flag

    def __init__(self,name=None,age=None):     if name:
            self.name = name
        if age:
            self.age = age

a1 = A(‘alex‘,84)
print(a1)               #<__main__.A object at 0x00000241BF577BA8>
a2 = A(‘alex‘,83)
print(a2)               #<__main__.A object at 0x00000241BF577BA8>
a3 = A(‘alex‘)
print(a3)               #<__main__.A object at 0x00000241BF577BA8>
print(a1.__dict__)      #{‘name‘: ‘alex‘, ‘age‘: 83}
print(a2.__dict__)      #{‘name‘: ‘alex‘, ‘age‘: 83}
print(a3.__dict__)      #{‘name‘: ‘alex‘, ‘age‘: 83}

# 保证一个类无论 被实例化多少次,只开辟一次空间,始终使用的是同一块内存地址

3. __del__方法

import time

class A:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __del__(self):
        # 只和del obj语法有关系,在执行del obj之前会来执行一下__del__中的内容
        print(‘执行我啦‘)

a = A(‘alex‘, 84)
print(a.name)
print(a.age)
del a  # 手动删除对象a 就直接执行__del__
time.sleep(1)
# 如果不手动执行del 会在所有代码执行完成后 自动执行del a 这时候就会先睡一秒在打印‘__del__‘中的内容
# 在所有的代码都执行完毕之后,所有的值都会被python解释器回收
python解释器清理内存:  1.我们主动删除 del obj  2.python解释器周期性删除  3.在程序结束之前 所有的内容都需要清空  既然python解释器可以周期性的清理内存 为什么我们还要手动去删除一些数据呢?  因为在归还一些操作系统的资源的时候还有包括文件\网络\数据库连接的时候使用,  我们需要先将这些接口关闭了之后再删除内容,不然内容删除了,这些打开的接口依然存在,会影响后面对系统资源等一些数据的调用
import time
class A:
    def __init__(self,path):
        self.f = open(path,‘w‘)
    def __del__(self):
        ‘‘‘归还一些操作系统的资源的时候使用‘‘‘
        ‘‘‘包括文件\网络\数据库连接‘‘‘
        print(111)
        self.f.close()    #在删除内存的时候执行__del__ 先将文件接口关闭

a = A(‘userinfo‘)
time.sleep(1)

4. __call__

class A:
    def call(self):     #当然也可以自己手动写一个call方法实现和__call__一样的功能
        print(‘in call‘)

    def __call__(self, *args, **kwargs):
        print(‘in __call__‘)

A()()           #实例化+调用  相当于obj = A()和obj()
#如果没有__call__会报错 ‘A‘ object is not callable
obj = A()
obj.call()      #调用自己写的call方法实现和__call__一样的功能
5 __enter__和__exit__ 用在with的上下文处理
 
class File:
    def __enter__(self):
        print(‘start‘)

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(‘exit‘)

with File():
    print(‘wahaha‘)

‘‘‘
输出:
start
wahaha
exit

和with组合编写一个文件操作类:

import pickle

class Mypickle_dump:        #写文件
    def __init__(self, path, mode=‘ab‘):
        self.path = path
        self.mode = mode

    def __enter__(self):
        self.f = open(self.path, self.mode)
        return self

    def dump(self, value):
        pickle.dump(value, self.f)

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()

with Mypickle_dump(‘mypickle‘, ‘ab‘)as f:    #读文件
    f.dump(‘1‘)
    f.dump(‘2‘)
    f.dump(‘3‘)
    f.dump(‘4‘)
    f.dump(‘你好啊‘)

class Mypickle_load:
    def __init__(self, path, mode=‘rb‘):
        self.path = path
        self.mode = mode

    def __enter__(self):
        self.f = open(self.path, self.mode)
        return self

    def load(self):
        while 1:
            try:
                yield pickle.load(self.f)
            except EOFError:
                break

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()

with Mypickle_load(‘mypickle‘, ‘rb‘)as f:
    for i in f.load():
        print(i)
    

with 和装饰器的区别:

  都是在一个函数的前后添加功能,但是装饰器装饰一次之后,后面再次使用都是被装饰过的,而with每次使用都得再次调用


import time
class Timer:
    def __enter__(self):
        self.start = time.time()
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(time.time() - self.start)

def func():
    print(‘wahaha‘)
    time.sleep(1)
    print(‘qqxing‘)

with Timer():
    func()

 
 


原文地址:https://www.cnblogs.com/stron/p/10642123.html

时间: 2024-10-08 23:22:07

面向对象进阶---魔术方法的相关文章

对php面向对象中魔术方法的认识

<?php//header(charset="utf8");    //echo 'hey 这里是描述我对php 面向对象中各种魔术方法的认识.';/* *魔术方法是在一些特定情况下会自动调用的一些php系统自定义函数 *这些函数都很有个性,他们统一以__两个 _ (下划线)开头. * 下面对于php 中这些常用的魔术方法一些个人认识. **/class demo {    public $name;    public $age; //当实例化这个类,首先会自动调用的方法 __

PHP面向对象之魔术方法复习

魔术方法复习 2014-9-2 10:08:00 NotePad++ By jiancaigege 飞鸿影~========================= 1.__construct() 构造方法 用于类实例化时自动运行的方法 常用于初始化成员属性值等 2.__destruct() 析构函数 用于类销毁时自动运行的方法 常用语销毁资源.关闭资源等 3.__set($param,$value) 用于给对象中非公有的成员属性设置值时自动调用的方法 例如: 1 public function __

面向对象之魔术方法

魔术方法是一种特殊的系统定义的函数方法,写在我们自定义的类中,不需要我们去调用,满足条件后自动调用.PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法.所以在定义类方法时,除了上述魔术方法,建议不要以 __ 为前缀.魔术方法现有15种,__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toStri

PHP面向对象的魔术方法

<?php/** * Created by PhpStorm. * User: fu * Date: 2017/7/19 * Time: 9:41 */ class Person{ protected $name; private $age; private $mobile; function __construct($name, $age) { $this->name = $name; $this->age = $age; } /** * 测试使用的不能直接访问的函数 * @param

[麦先生]PHP面向对象中常见的魔术方法以及关键字

麦先生引言:在学习php面向对象的编程思想中,我们会遇到很多的能够自动调用的魔术方法,每个魔术方法都有其特定的触发场景,但其根本目的是在于编写和实际使用过程中阻止程序报错而生; 常见的魔术方法有:music=> gusic(根据首字母拼音大写由gusic联想到music)    以及构造,析构方法,以及特殊的关键字fsci -- cats 和 ai 魔术方法                触发场景 <!--gusic---------------------------------------

前端学PHP之面向对象系列第二篇——魔术方法

显示目录 目录 [1]构造方法 [2]析构方法 [3]不可访问属性[4]对象复制[5]字符串[6]对象不存在[7]自动加载类[8]串行化[9]函数调用 前面的话 php在面向对象部分有很多相关的魔术方法,这些方法为面向对象实现提供了便利,本文将详细介绍魔术方法 构造方法 大多数类都有一种称为构造函数的特殊方法.当创建一个对象时,它将自动调用构造函数,通常用它执行一些有用的初始化任务 构造函数的声明与其它操作的声明一样,只是其名称必须是两个下划线__construct( ).这是PHP5中的变化:

php面向对象类中常用的魔术方法

php面向对象类中常用的魔术方法 1.__construct():构造方法,当类被实例化new $class时被自动调用的方法,在类的继承中可以继承与覆盖该方法,例: //__construct() class construct{ public function __construct(){ $this->var = "this is var"; } } class con2 extends construct{ public function __construct(){ $

PHP面向对象常见的关键字和魔术方法

在PHP5的面向对象程序设计中提供了一些常见的关键字,用来修饰类.成员属性或成员方法,使他们具有特定的功能,例如final.static.const等关键字.还有一些比较实用的魔术方法,用来提高类或对象的应用能力,例如__call().__toString().__autoload等. ①final关键字的应用 final关键字的作用如下:a.实用final标识的类,不能被继承.b.在类中使用final标识的成员方法,在子类中不能被覆盖. 在下面的例子中声明一个MyClass类,并使用final

面向对象中所有的魔术方法和关键字

魔术方法构造函数,对类里面成员进行初始化function __construct(){}析构函数,在对象释放的时候自动执行function __destruct(){} __set方法function __set($name,$value){}                                                          __set和__get  主要用在封装里面__get方法function __get($name){} __tostring()方法