绑定方法、非绑定方法与反射、内置方法
一、绑定方法与非绑定方法
- 类中定义的函数分为两大类
- 绑定方法
- 非绑定方法
- 绑定方法又分为
- 绑定到对象的对象方法
- 绑定到类的类方法
- 在类中正常定义的函数默认是绑定到对象的,而为某个函数加上装饰器@classmethod后,该函数就绑定到了类
- classmethod
- 是一个装饰器,给类内部定义方法中装饰,将类内部的方法变为"类的绑定方法"
- staticmethod
- 是一个装饰器,给类内部定义方法中装饰,将类内部的方法变成"非绑定方法"
- 对象的绑定方法
- 由对象来调用,由谁来调用,会将谁(对象)当作第一个参数传入
- 类的绑定方法
- 由类来调用,由谁来调用,会将谁(类)当作第一个参数传入
- 非绑定方法
- 可以由对象或类来调用,谁来调用都是一个普通方法(普通函数),方法需要传入几个参数,就得传入几个参数
- 绑定方法
# 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中,绑定到类的方法与绑定到对象的方法时严格区分开的
- 非绑定方法
为类中某个函数加上装饰器@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()
总结绑定方法与非绑定方法的使用:
若类中需要一个功能,该功能的实现中需要引用对象则将其定义成对象、需要引用类则将其定义成类方法、无需引用类或对象则将其定义成静态方法
二、内置方法
isinstance
与issubclass
是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)
-
hasattr
# hasattr # 通过字符串x 判断对象中是否有 x 属性 print(hasattr(foo_obj, 'x')) # True print(hasattr(foo_obj, 'y')) # True print(hasattr(foo_obj, 'z')) # False
-
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
-
setattr
# setattr # 为foo_obj 设置一个属性z,值为30 setattr(foo_obj, 'z', 30) print(getattr(foo_obj, 'z')) # 30
-
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()