绑定方法、非绑定方法与反射、内置方法

绑定方法、非绑定方法与反射、内置方法

一、绑定方法与非绑定方法

  • 类中定义的函数分为两大类
    • 绑定方法
    • 非绑定方法
  • 绑定方法又分为
    • 绑定到对象的对象方法
    • 绑定到类的类方法
  • 在类中正常定义的函数默认是绑定到对象的,而为某个函数加上装饰器@classmethod后,该函数就绑定到了类
  • classmethod
    • 是一个装饰器,给类内部定义方法中装饰,将类内部的方法变为"类的绑定方法"
  • staticmethod
    • 是一个装饰器,给类内部定义方法中装饰,将类内部的方法变成"非绑定方法"
  • 对象的绑定方法
    • 由对象来调用,由谁来调用,会将谁(对象)当作第一个参数传入
  • 类的绑定方法
    • 由类来调用,由谁来调用,会将谁(类)当作第一个参数传入
  • 非绑定方法
    • 可以由对象或类来调用,谁来调用都是一个普通方法(普通函数),方法需要传入几个参数,就得传入几个参数
  1. 绑定方法
# classmethod_Demo
class DB:
    __data = 'tank is very handsome'

    def __init__(self, user, pwd, role):
        self.user = user
        self.pwd = pwd
        self.role = role

    @classmethod
    def init(cls, user, pwd, role):  # cls--->指的是类
        # 在类方法内部调用类产生一个实例 ---> 对象
        return cls(user, pwd, role)

    # 查看数据方法
    @classmethod
    def check_db(cls, user, pwd, role):
        # 在类内部调用产生一个实例--->  对象
        obj = cls(user, pwd, role)

        # 查看数据前,必须要通过效验
        if obj.user == 'tank' and obj.pwd == '123' and obj.role == 'admin':
            print('效验通过...')
            print(cls.__data)
            return cls.__data


DB.check_db('tank', '123', 'admin')

绑定到类的方法就是专门给类用的,但其实对象也可以调用,只不过自动传入的第一个参数仍然是类,也就是说这种调用时没有意义的,并且容易混淆,这也是python的对象系统与其他面向对象语言系统的区别之一,比如Smalltalk和Ruby中,绑定到类的方法与绑定到对象的方法时严格区分开的

  1. 非绑定方法

为类中某个函数加上装饰器@staticmethod后,该函数就变成了非绑定方法,也成为静态方法。该方法不与类或对象绑定,类与对象都可以来调用它,但它就是一个普通的函数而已,因而没有传值那么一说

import uuid	# 用于产生随机字符串的模块
class MySQL:
    def __init__(self, host, port):
        self.id = self.create_id()
        self.host = host
        self.port = port
    @staticmethod
    def create_id():
        return uuid.uuid1()

conn = MySQL('127.0.0.1', 3306)
print(conn.id)

# 类或对象来调用create_id 发现都是普通函数,而非绑定到谁的方法
MySQL.create_id()
conn.create_id()

总结绑定方法与非绑定方法的使用:

若类中需要一个功能,该功能的实现中需要引用对象则将其定义成对象、需要引用类则将其定义成类方法、无需引用类或对象则将其定义成静态方法

二、内置方法

isinstanceissubclass是python的内置模块

  • isinstance
    • 判断一个对象是否是另一个类的实例
    • 返回布尔值,如果是:True ;如果不是:False
  • issubclass
    • 判断一个类是否是另一个类的子类
    • 返回布尔值,如果是:True ;如果不是:False
# isinstance
class Foo:
    pass
class Boo:
    pass
foo_obj = Foo()
boo_obj = Boo()
print(isinstance(foo_obj, Foo))	# True
print(isinstance(boo_obj, Foo))	# False
# 顺序不可以换,否则会报错,第一个参数一定是对象,第二个参数一定是类

# issubclass
class Father:
    pass
class Sub(Father):
    pass
class Foo:
    pass
print(issubclass(Sub, Father))	# True
print(issubclass(Foo, Father))	# False
# 顺序也不可以换,换了不会报错但是结果会错,都是False
# 第一个参数是子类,第二个是父类

三、反射

反射指的是通过"字符串"对<对象>的属性进行操作

  • hasattr
    • 通过"字符串"判断对象的属性或方法是否存在
  • getattr
    • 通过"字符串"获取对象的属性或方法
  • setattr
    • 通过"字符串"设置对象的属性或方法
  • delattr
    • 通过"字符串"删除对象的属性或方法

注意:反射的四个方法都市python内置的

class Foo:
    def __init__(self, x, y):
        self.x = x
        self.y = y

foo_obj = Foo(10, 20)
  1. hasattr

    # hasattr
    # 通过字符串x 判断对象中是否有 x 属性
    print(hasattr(foo_obj, 'x'))	# True
    print(hasattr(foo_obj, 'y'))	# True
    print(hasattr(foo_obj, 'z'))	# False
    
  2. getattr

    # getattr
    res1 = getattr(foo_obj, 'x')
    res2 = getattr(foo_obj, 'y')
    res3 = getattr(foo_obj, 'z', None)
    # 若属性不存在,则返回自己自定义的默认值
    print(res1)		# 10
    print(res2)		# 20
    print(res3)		# None
    
  3. setattr

    # setattr
    # 为foo_obj 设置一个属性z,值为30
    setattr(foo_obj, 'z', 30)
    print(getattr(foo_obj, 'z'))	# 30
    
  4. delattr

    # delattr
    delattr(foo_obj, 'z')
    print(hasattr(foo_obj, 'z'))	# False
    
  • 反射应用
class FileControl:
    def run(self):
        while True:
            # 让用户输入上传或下载功能的命令
            user_input = input('请输入上传(upload)或下载(download)功能:').strip()
            # 通过用户输入的字符串判断方法是否存在,然后调用相应的方法
            if hasattr(self, user_input):
                func = getattr(self, user_input)
                func()
            else:
                print('输入有误!')
    def upload(self):
        print('文件正在上传...')

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

file_control_obj = FileControl()
file_control_obj.run()
原文地址:https://www.cnblogs.com/YGZICO/p/11959767.html