Python-面向对象之高级进阶

classmethod与staticmethod

装饰器,均可以装饰类内部的方法

classmethod :使该方法绑定给类来使用,称为类的绑定方法

staticmethod:使该方法变成了一个普通函数,即非绑定方法

再来复习一下对象的绑定方法特殊之处

对象的绑定方法特殊之处:

​ - 由对象调用,会将对象当做第一个参数传入该方法

类的绑定方法特殊之处:

​ - 由类来调用,会将类名当做第一个参数传入该方法

上代码

import settings
import uuid
import hashlib


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

    # 将该方法装饰成类的绑定方法
    # 登录认证,从配置文件中读取用户名密码
    @classmethod
    def login_auth(cls):
        obj = cls(settings.USER,settings.PWD)
        return obj

    # 将该方法装饰成一个普通的函数,不会自动传值,对象or类都可以调用
    @staticmethod
    def create_id():
        uuid_obj = uuid.uuid4()
        return hashlib.md5(str(uuid_obj).encode("utf-8")).hexdigest()

    
    def index(self):
        print("验证通过,显示主页")


# 用classmethod 装饰过的方法返回一个对象
obj = People.login_auth()       # 在该方法中通过读取配置文件的参数实例化出一个对象
obj.index()     # 将返回出去的对象调用其他方法

# 调用 staticmethod 装饰过的方法,即普通函数,由类调用,也可以对象调用
print(People.create_id())

面向对象高级

isinstance、issubclass

python中内置的函数,均传入两个参数(参数1,参数2)

isinstance:判断一个对象是否是一个类的实例(判断一个对象是否是已知类型)

issubclass:判断一个类是否是另一个类的子类。

class Foo:
    pass

class Bar(Foo):
    pass

# isinstance    判断对象是否是类的实例
f = Foo()
print(isinstance(f,Foo))        # True
l = [1,2]
print(isinstance(l,list))       # True


# issubclass    判断类是否是另一个类的子类
print(issubclass(Bar,Foo))      # True

反射

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

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

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

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

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

上代码

class People:
    country = "China"
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

# hasattr   传两个参数,判断对象有没有属性
p1 = People("qinyj",18,"nan")
print(hasattr(p1,"country"))        # True

# getattr   传三个参数,也可以传两个参数,如果属性不存在报错
p2 = People("qinyj",18,"nan")
print(getattr(p2,"country","China"))

# setattr   传两个参数,设置对象的属性
p3 = People("qinyj",18,"nan")
setattr(p3,"country","China")
print(getattr(p3,"country",))

# delattr   传两个参数,删除对象的属性
p4 = People("qinyj",18,"nan")
# delattr(p4,"country")
# print(getattr(p4,"country",))
# 反射练习
class Movie:
    def input_cmd(self):
        print("请输入命令")
        while True:
            cmd = input("请输入执行的方法名").strip()
            
            # hasattr 与 getattr 连用实例
            if hasattr(self,cmd):
                getattr(self,cmd)()
                
    def upload(self):
        print("电影开始上传")

    def download(self):
        print("电影开始下载")
m = Movie()
m.input_cmd()

魔法方法(类内置方法)

凡是在类内部定义,"__名字__"的方法都称之为魔法方法,又称类的内置方法

__init__:初始化函数,在类调用时自动触发

__str__:打印对象的时候自动触发

__del__:删除对象的名称空间,最后才执行

__getattr__:对象.属性获取属性,没有获取到值自动触发

__setattr__:对象.属性赋值的时候自动触发

__call__:在帝乡被调用时自动触发

__new__:在__init__前自动触发,产生一个空的对象

class Foo(object):
    '''
    以下均是类的内置方法,
    '''

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

    def __init__(self):
        print("在类调用时触发")

    def __str__(self):
        return "在打印对象的值时触发"

    def __del__(self):
        print("最后执行该方法,删除内存地址")

    def __getattr__(self, item):
        return "没有获取对象属性时触发"

    def __setattr__(self, key, value):
        print("设置对象属性值时触发")
        print(key,value)
        self.__dict__[key] = value

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

f = Foo()
# 打印对象
print(f)
# <class '__main__.Foo'>
# 在类调用时触发
# 在打印对象的值时触发
# 最后执行该方法,删除内存地址

# 获取对象属性x
print(f.x)
# <class '__main__.Foo'>
# 在类调用时触发
# 在打印对象的值时触发
# 没有获取对象属性时触发
# 最后执行该方法,删除内存地址


# 对象赋值新的属性
f.x = "x"
print(f.x)
# <class '__main__.Foo'>
# 在类调用时触发
# 在打印对象的值时触发
# 没有获取对象属性时触发
# 设置对象属性值时触发
# x x
# x
# 最后执行该方法,删除内存地址

# 对象调用
f()
# <class '__main__.Foo'>
# 在类调用时触发
# 在打印对象的值时触发
# 没有获取对象属性时触发
# 设置对象属性值时触发
# x x
# x
# 调用对象时触发
# 最后执行该方法,删除内存地址



class MyFile:
    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(res)

    # 使用del内置函数,在最后执行,就会调用关闭文件操作
    def __del__(self):
        self.f.close()
        print("文件关闭成功")

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

print("程序结束,对象将被销毁!")

单例模式

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

实例化多个对象时会产生不同的内存地址,单例可以让所有调用者,在调用类产生对象的情况下都指向同一份内存地址,例如,打开文件

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

class File:
    __instance = None

    # 单例模式1
    # 使用类的绑定方法,
    @classmethod
    def singleton(cls,file_name):
        # 类中设置一个私有属性__instance,
        # 在类自己调用完成产生一个对象,将这个对象赋值给类的这个属性,
        # 如果这个类属性有对象了,就说明已经实例化过了无需再次实例化,直接返回
        # 外部调用者只需调用其方法即可使用单例模式操作对象
        if not cls.__instance:
            obj = cls(file_name)
            cls.__instance = obj
        return cls.__instance

    # 单例模式2
    # 使用__new__产生一个空的对象,相当于创建一个空的对象,调用时相当于多个变量指向这个对象
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = object.__new__(cls)
        return cls.__instance
    '''
    实例化出来的对象内存地址一样
    <__main__.File object at 0x000000000295C668>
    <__main__.File object at 0x000000000295C668>
    <__main__.File object at 0x000000000295C668>
    '''


    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()
        print(res)

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

f1 = File("settings.py")
f2 = File("settings.py")
f3 = File("settings.py")
print(f1)
print(f2)
print(f3)
# 如下:产生的三个对象 内存地址均不同
# <__main__.File object at 0x000000000298C6D8>
# <__main__.File object at 0x000000000298C710>
# <__main__.File object at 0x000000000298C6A0>


# 让其成为单例模式调用
f1 = File.singleton("settings.py")
f2 = File.singleton("settings.py")
f3 = File.singleton("settings.py")
print(f1)
print(f2)
print(f3)
# 如下:产生的三个对象 内存地址均相同
# <__main__.File object at 0x0000000009F6F908>
# <__main__.File object at 0x0000000009F6F908>
# <__main__.File object at 0x0000000009F6F908>
posted @ 2019-10-12 16:37  GeminiMp  阅读(588)  评论(0编辑  收藏  举报