面对对象(特殊方法)

一、__str__ 用法:

  1.1 定义:
    如果不实现str方法,那么对象打印出来只是对象的内存地址
    直接打印这个实例化对象时,自动触发__str__方法
    使用字符串格式化(%s/f{name}/{}.format)时,自动触发__str__方法

  1.2 示例:

  
# 示例:

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

    # 如果不实现str方法,那么对象打印出来只是对象的内存地址
    def __str__(self):
        '''打印这个对象的时候 自动触发__str__'''
        '''使用%s进行字符串的拼接的时候 自动触发__str__'''
        return '%s,%s,%s' % (self.name, self.price, self.period)


python = Course('python', 25000, '6 months')  # 实例化

print(python)  # 普通打印

print('course %s' % python)  # 格式化字符串方式一
print(f'course {python}')  # 格式化字符串方式二
View Code

二、 __str__ 与 __repr__ 用法:

  2.1 三种类型:

    1、如果str存在,repr也存在:
      那么print(obj)和使用字符串格式化format,%s这两种方式 调用的都是__str__
      而repr(obj)和%r格式化字符串,都会调用__repr__
    2、如果str不存在,repr存在:
      那么print(obj),字符串格式化format,%s,%r 和repr(obj)都调用__repr__
    3、如果str存在,repr不存在
      那么print(obj)和使用字符串格式化format,%s这两种方式 调用的都是__str__
      repr(obj)和%r格式化字符串 都只会只打印出内存地址

  2.2 示例:

  
# 示例:

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)

    def __str__(self):
        return self.name    # 字符串方法必须有一个return返回值,且必须为字符串类型


python = Course('python', 25000, '6 months')

print(python)
print('course %s' % python)
print(f'course {python}')

print(repr(python))
print('course %r' % python)



# str方式:
print(str('123'))
# repr方式:
print(repr('123'))
View Code

三、 __new__ 构造方法:

  3.1 定义:
    创建对象的时候使用,通过构成方法,创建一个self对象
    通过构造方法,实现单例模式

  3.2 实例化:

    定义一个类时,先开辟一块儿空间,如果定义了__new__方法,使用的是类内部__new__方法
    如果我们的定义的类中是没有__new__方法,创建实例对象时调用object类的__new__方法
    __new__方法就是在内存中开辟一块属于这个对象(self)的空间,并且在这个空间中存放一个类指针

  3.3 构造方法示例:

  
# 示例:

class Foo:

    # cls永远不能使self参数,因为self在之后才被创建
    def __new__(cls, *args, **kwargs):  # __new__创造self对象
        print('in new')   # 先执行
        obj = object.__new__(cls)
        print(obj)
        return obj

    def __init__(self):
        print('init', self)    # 后执行


Foo()   # 实例化,先执行__new__方法,后执行__init__方法
View Code

  3.4 单例模式:

    定义:

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

    示例1:

  
# 示例:

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):
        self.name = name
        if age:
            self.age = age

a1 = A('alex',84)
print(a1)
a2 = A('alex',83)
print(a2)
a3 = A('alex')
print(a3)
print(a1.age)
View Code

    示例2:

# 装饰器实现单例模式
def singleton(cls):
    _instance = {}

    def _singleton(*args, **kwargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kwargs)
        return _instance[cls]

    return _singleton


@singleton
class B(object):
    def __init__(self, name):
        self.name = name


b1 = B("apple")
b2 = B("orange")
print(b1, b2)

   示例3:

# 通过类实现单例模式
# 需要加锁,否则多线程会出问题
import time
import threading


class Singleton(object):
  # 实例化Lock _instance_lock
= threading.Lock() def __init__(self): time.sleep(1) # 实现一个静态方法 @classmethod def instance(cls, *args, **kwargs): # 上下文的形式加锁 with Singleton._instance_lock: if not hasattr(Singleton, "_instance"): Singleton._instance = Singleton(*args, **kwargs) return Singleton._instance def task(arg): obj = Singleton.instance() print(obj) for i in range(10): t = threading.Thread(target=task, args=[i, ]) t.start() time.sleep(10) obj = Singleton.instance() print(obj)

   示例4:

# 因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。
# 们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象
# a.py
class Singleton(object):
    def foo(self):
        pass
singleton = Singleton()

# 使用时,直接在a.py文件中导入此文件中的对象,这个对象即是单例模式的对象 from a import singleton

  示例5:元类创建单例模式

import threading

class SingletonType(type):
    _instance_lock = threading.Lock()
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with SingletonType._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = super().__call__(*args, **kwargs)
        return cls._instance
        
class Singleton(metaclass=SingletonType):
    def __init__(self):
        pass
 
obj1 = Singleton()
obj2 = Singleton()
print(obj1 is obj2)

四、 __del__析构方法:  

  4.1 定义:
    1、类中定义del方法,则会执行类中的__del__方法,此处的__del__方法只对类的对象做析构,与属性的析构方法无关。
    2、在所有的代码都执行完毕之后,所有的值都会被python解释器回收。    

    3、如果类中未自定义__del__方法,则会执行父类(object)类中的__del__方法实现某析构,比如在文件操作后,在__del__方法中关闭文件句柄等,可以及时归还系统资源。

  4.2 析构方法(__del__)的作用:

    1、归还系统资源,例如关闭文件句柄,关闭套接字等等

    2、析构方法一定是在删除对象(self)之前执行完成的,否则无法归还系统资源

  4.2 示例:

  
# 示例一:

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)
time.sleep(1)

del a   # 通过__del__方法删除对象 a



# 示例二:
# 与文件操作相关,__del__方法归还系统资源

import time
class A:
    def __init__(self,path):
        self.f = open(path,'w')
    def __del__(self):
        '''归还一些操作系统的资源的时候使用'''
        '''包括文件\网络\数据库连接'''
        self.f.close()


a = A('userinfo')
time.sleep(1)
View Code

五、  __call__方法:  

  5.1 定义:
    实例化对象 + () :调用对象时,自动触发__call__中的内容

  5.2 示例:

  
# 示例:

class A:
    def call(self):
        print('in call')
    def __call__(self, *args, **kwargs):
        print('in __call__')

A()()  # 调用__call__方法

obj = A()  # 实例化
obj()   # 调用__call__方法

obj.call()  # 自定义的类方法
View Code

六、 with的上下文处理(enter,exit):  

  6.1 定义:
    __enter__方法 + __exit__方法结合使用,实现上下文管理

    返回值:__enter__方法 的返回值

  6.2 示例:

# 示例:

# 写文件:
import pickle
class MypickleDump:
    def __init__(self, path, mode='ab'):
        self.path = path
        self.mode = mode

    # with的起始函数
    def __enter__(self):
        self.f = open(self.path, self.mode)
        return self

    # 文件写入
    def dump(self, obj):
        pickle.dump(obj, self.f)

    # with的终止函数
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()


with MypickleDump('pickle_file') as pickle_obj:  # 实例化对象
    pickle_obj.dump({1, 2, 3})



# 读文件:
class MypickelLoad:
    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 loaditer(self):
        while True:
            # 异常处理,读取所有文件
            try:
                ret = pickle.load(self.f)
                yield ret
            except EOFError:
                break

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


with MypickelLoad('pickle_file') as mypic:  # 实例化对象
    for obj in mypic.loaditer():
        print(obj)
View Code

 七、__module__方法

  __module__ 描述:

  • 如果当前模块为顶层模块执行 则打印__main__
  • 如果当前模块为被调用模块的时候 打印当前模块的名称

  test.py文件:

def func():
    print("hello world!")


if __name__ == '__main__':
    func()
    print(func.__module__)


打印结果:
hello world!
__main__

  test2.py文件,通过导入test.py文件执行func函数:

from day9020190712.test import func

if __name__ == '__main__':
    func()
    print(func.__module__)


打印结果:
hello world!
day9020190712.test

 八、子类继承父类的三种方式

class Dog(Animal): #子类  派生类
    def __init__(self,name,breed, life_value,aggr):
        # Animal.__init__(self,name,breed, life_value,aggr)  #让子类执行父类的方法 就是父类名.方法名(参数),连self都得传
        super().__init__(name,life_value,aggr)  #super关键字  ,都不用传self了,在新式类里的
        # super(Dog,self).__init__(name,life_value,aggr)  #上面super是简写
        self.breed = breed
def bite(self,person): #狗的派生方法 person.life_value -= self.aggr

   # 重构父类方法的优点:代码更简洁。缺点:增加了耦合性,后期维护困难
def eat(self): #父类方法的重写 super().eat() # 执行父类方法 print('dog is eating') # 重写eat新增加的代码方法

九、__getitem__方法

class A(object):

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

    def __getitem__(self, item):
        print(item)


a = A("alex", 12)
print(a.age)
a["name"]
a["age"]

# 答案:
12
name
age

十、重写__setitem__方法

class Foo(object):
    def __setitem__(self, key, value):
        print(key,value)

obj = Foo()
obj["xxx"] = 123   #给对象赋值就会去执行__setitem__方法

十一、继承dict方法

  11.1 继承dict方法:

class Foo(dict):
    pass

obj = Foo()
obj["xxx"] = 123
print(obj)

#答案:
{"xxx": 123}

  11.2 继承dict,重写__init__方法:

  注意:重写__init__方法时,记得要继承父类的__init__方法

 
class Foo(dict):
    def __init__(self,val):
        super(Foo,self).__init__(val)  # 继承父类的__init__方法
obj = Foo({"xxx": 123}) print(obj)

#答案
{"xxx": 123}

十二、__getattr__ 方法

class A(object):

    def __getattr__(self, item):
        print(item)


a = A()
a.name
a.age

# 答案:
name
age

十三、__eq__方法

  返回结果只跟__eq__方法的return返回值有关。

class A(object):

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

    def __eq__(self, other):
        return self.name == other.name


a1 = A("alex", 12)
a2 = A("egon", 13)
print(a1 == a2)

# 答案 False

十四、__gt__方法

class A(object):

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

    def __gt__(self, other):
        return self.age > other.age


a1 = A("alex", 12)
a2 = A("egon", 18)
a3 = A("andy", 15)

lst = [a1, a2, a3]
lst.sort()

print([a.age for a in lst])

# 答案:
[12, 15, 18]

 

posted @ 2019-04-02 20:38  Amorphous  阅读(231)  评论(0编辑  收藏  举报