classmethod,staticmethod,反射,魔法方法,单例模式

classmethod

classmethod是一个装饰器,可以装饰给类内部的方法,使该方法绑定给类来使用

  1. 对象绑定方法特殊之处:由对象来调用,会把对象当作第一个参数传给该方法
  2. 类绑定方法特殊之处:由类来调用,会把类当作第一个参数传给该方法
class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def tell_info(cls):
        print(cls)
        print('此处是类方法。。。')


People.tell_info()
'''
<class '__main__.People'>
此处是类方法。。。
'''

小练习:

# settings.py
'''
USER = 'tank'
PWD = '123'
'''


import settings

class Teacher:
    def __init__(self, user, pwd):
        self.user = user
        self.pwd = pwd

    # 显示主页
    def index(self):
        if self.user == 'tank' and self.pwd == '123':
            print('验证成功,显示主页')

    @classmethod
    def login_auth(cls):
        obj = cls(settings.USER, settings.PWD)
        return obj


obj = Teacher.login_auth()
obj.index()

staticmethod

staticmethod是一个装饰器,可以装饰给类内部的方法,使得该方法既不绑定类,也不绑定对象

import settings
import uuid
import hashlib

class Teacher:
    def __init__(self, user, pwd):
        self.user = user
        self.pwd = pwd

    # 显示主页
    def index(self):
        if self.user == 'tank' and self.pwd == '123':
            print('验证成功,显示主页')

    @classmethod
    def login_auth(cls):
        obj = cls(settings.USER, settings.PWD)
        return obj

    @staticmethod
    def create_id():
        uuid_obj = uuid.uuid4()
        md5 = hashlib.md5()
        md5.update(str(uuid_obj).encode('utf-8'))
        return md5.hexdigest()


print(Teacher.create_id())
t1 = Teacher('tank', 123)
print(t1.create_id()) 

instance

python内置函数,可以传入两个参数,用于判断参数1是否是参数2的一个实例。

判断一个对象是否是一个类的实例

class Foo:
    pass

foo_obj = Foo()
print(foo_obj)
print(foo_obj.__class__.__dict__)
print(foo_obj in Foo.__dict__)   # 判断一个对象是否是类的实例

print(isinstance(foo_obj, Foo))  # 判断一个对象是否是类的实例

issubclass

python内置函数,可以传入两个参数,用于判断参数1是否是参数2的一个子类

判断一个类是否是一个类的子类

class Foo:
    pass


class Goo(Foo):
    pass


print(issubclass(Goo, Foo))  # True

反射

指的是通过“字符串”对 对象或类的属性进行操作

hasatter

通过字符串,判断字符串是否是对象或类的属性

class People:
    country = 'China'

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


p = People('tank', 18, 'male')
# 普通方式
print('name' in p.__dict__)
# hasatter
print(hasattr(p, 'name'))
print(hasattr(p, 'country'))

getatter

通过字符串,获取对象或类的属性4

# 普通方式
print(p.__dict__.get('name'))
# getatter
print(getattr(p, 'name', 'jason'))

setatter

通过字符串,设置对象或类的属性

setattr(p, 'level', '3.0')
print(hasattr(p, 'level'))

delatter

通过字符串,删除对象或类的属性

delattr(p, 'name')

print(hasattr(p, 'name'))

反射小练习

class Movie:
    def input_cmd(self):
        print('请输入命令......')
        while True:
            cmd = input('请输入执行的命令:').strip()

            # 若输入的cmd命令是当前对象的属性
            if hasattr(self, cmd):
                method = getattr(self, cmd)
                method()


    def upload(self):
        print('正在上传...')

    def download(self):
        print('正在下载...')


obj = Movie()
obj.input_cmd()

魔法方法

凡是类内部定义,以__开头,__结尾的方法都称之为魔法方法,又称类的内置方法

魔法方法会在某些条件成立的时候触发

__init__:在掉用类时触发
__str__:在打印对象时触发

__del__:会在程序结束时触发,销毁对象, 该方法会在最后执行

__getattr__:会在对象.属性时,属性没有的情况下才会触发

__setattr__:会在对象.属性 = 属性值的时候触发

__new__:会在__init__执行前触发
__call__:会在对象调用时触发

class Foo:

    def __new__(cls, *args, **kwargs):
        print(cls)
        return object.__new__(cls)   # 真正产生一个对象

    # 若当前类的__new__没有return一个空对象,则不会触发
    def __init__(self):
        print('在调用类时触发...')

    def __str__(self):
        print('在打印对象时触发')
        # 必须要有一个返回值,该返回值必须是字符串
        return '我是Foo实例化出的对象'

    def __del__(self):
        print('对象被销毁前执行该程序')

    def __getattr__(self, item):
        print('会在对象.属性时,属性没有的情况下才会触发')
        print(item)
        # 若想打印属性的结果,必须要return一个值

    # 注意:执行该方法时,外部“对象.属性=属性值”时无效
    def __setattr__(self, key, value):
        print('会在对象.属性 = 属性值的时候触发')
        print(key, value)
        print(self, 111)
        self.__dict__[key] = 1234

    def __call__(self, *args, **kwargs):
        print(self)
        print('调用对象时触发')


obj = Foo()
# print(obj)
# print(obj.x)
# obj.x = 3
# print(obj.x)
#
# obj()

魔法方法del应用:

class MyFile(object):
    def __init__(self, file_name, mode='r', encoding='utf-8'):
        self.file_name = file_name
        self.mode = mode
        self.encoding = encoding

    def file_open(self):
        self.f = open(self.file_name, self.mode, encoding=self.encoding)

    def file_read(self):
        res = self.f.read()
        print(f'''
            当前文件名称:{self.file_name}
            当前文件内容:{res}
            ''')

    def __del__(self):
        self.f.close()
        print('文件关闭成功')

f = MyFile('settings.py')
f.file_open()
f.file_read()

单例模式

什么是单例

单例模式指的是单个实例,实例指的是调用类产生的对象

为什么要使用单例

实例化多个对象会产生不同的内存地址,单例可以调用者在调用同一个对象时,都指向同一个内存地址。例如打开文件。

单例的目的:为了减少内存的占用。

class File:
    def __init__(self, file_name, mode='r', encoding='utf-8'):
        self.file_name = file_name
        self.mode = mode
        self.encoding = encoding

    def open(self):
        self.f = open(self.file_name, self.mode, encoding=self.encoding)

    def read(self):
        res = self.f.read()
        return res

    def close(self):
        self.f.close()

obj1 = File('settings.py')
obj2 = File('settings.py')
obj3 = File('settings.py')
print(obj1)
print(obj2)
print(obj3)

'''
<__main__.File object at 0x00000143ACD7D978>
<__main__.File object at 0x00000143ACDA20B8>
<__main__.File object at 0x00000143ACDA2198>
'''

可以看出,实例化出三个对象,它们的地址都不相同

class File:

    __instance = None

    # 单例模式1
    @classmethod
    def singleton(cls, file_name):
        if not cls.__instance:
            obj = cls(file_name)
            cls.__instance = obj
        return cls.__instance

    def __init__(self, file_name, mode='r', encoding='utf-8'):
        self.file_name = file_name
        self.mode = mode
        self.encoding = encoding

    def open(self):
        self.f = open(self.file_name, self.mode, encoding=self.encoding)

    def read(self):
        res = self.f.read()
        return res

    def close(self):
        self.f.close()

obj1 = File.singleton('settings.py')
obj2 = File.singleton('settings.py')
obj3 = File.singleton('settings.py')
print(obj1)
print(obj2)
print(obj3)
'''
<__main__.File object at 0x000001A04F472198>
<__main__.File object at 0x000001A04F472198>
<__main__.File object at 0x000001A04F472198>
'''
class File:

    __instance = None

    # 单例模式2
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = object.__new__(cls)
        return cls.__instance

    def __init__(self, file_name, mode='r', encoding='utf-8'):
        self.file_name = file_name
        self.mode = mode
        self.encoding = encoding

    def open(self):
        self.f = open(self.file_name, self.mode, encoding=self.encoding)

    def read(self):
        res = self.f.read()
        return res

    def close(self):
        self.f.close()

obj1 = File('settings.py')
obj2 = File('settings.py')
obj3 = File('settings.py')
print(obj1)
print(obj2)
print(obj3)
'''
<__main__.File object at 0x00000184C9CD2198>
<__main__.File object at 0x00000184C9CD2198>
<__main__.File object at 0x00000184C9CD2198>
'''
posted @ 2019-10-13 18:36  SetCreed  阅读(469)  评论(0编辑  收藏  举报