绑定方法
在我们定义类的时候,会发现在类中会定义一些函数,我们称之为方法,那么对于我们进行实例化之后产生的实例,我们也可以使用这些方法,那么问题来了,这些方法到底是绑定给类的还是绑定给实例化后产生的对象的?如果是绑定给对象的,那么如何对类进行绑定方法呢?下面我们来进行分析:
绑定给对象的方法
在python中,如果按照正常的函数定义方式,来定义类中的方法,不加任何装饰,那么这些方法是绑定给类实例化后产生的对象的,可以通过对象名.方法名()
方式调用。下面通过代码进行演示:
class Student():
school = 'SH'
def __init__(self, name, age):
self.name = name
self.age = age
def tell_info(self, v):
print('name:%s, age: %s, salary:%s' % (self.name, self.age, v))
stu = Student('mary', 19)
# 对象来调用方法, 绑定给对象的方法由对象来调用,特殊之处是把对象自己当成第一个参数传递到方法里面
stu.tell_info(20000) # 本质就是stu.tell_info(stu,10)
绑定给类的方法
既然上面说了不添加任何装饰所定义的方法是绑定给对象的,那么绑定给类的方法就需要添加一些装饰了。在python中如果需要将某一个方法绑定给类,那么就需要在该方法定义的时候添加@classmethod
装饰器,见名知意,就说明该方法是绑定给类的方法,该装饰器的内部就完成了这样一个功能,在使用的时候通过类名.方法名()
调用,内部会自动将类作为第一个参数传给该方法。下面我们通过代码进行演示:
# 我们通过简单的mysql连接方式来举例,mysql连接需要ip和port
# 我们想要通过调用类里面的方法来返回一个对象
class Mysql():
def __init__(self, ip, port):
self.ip = ip
self.port = port
# 绑定给类的方法
@classmethod
def from_func(cls):
return cls('127.0.0.1', '3306')
def func(self):
self.__class__ # 可以通过此方式拿到产生对象的类名
# 类调用
Mysql.from_func() # 本质就是Mysql.from_func(Mysql)
总结:
通过上面的例子可以看出,方法既可以绑定给类,也可以绑定给对象,那么什么时候绑定给类,什么时候绑定给对象呢?我们是这样决定的,如果方法中用到了类名,那么就绑定给类,如果方法中用到了对象,那么就绑定给对象。
这时,就有人会问,如果方法中方法中既用到了类名,又用到了对象名,那么怎么办呢?哈哈,让小调皮要失望了,在将方法绑定给对象的时候,在方法内部可以通过self.__class__
来取代生成对象的类名,这样就可以同时实现用到类名和对象名了哦!
非绑定方法
上面说了绑定方法,那么,有人肯定会问,那么我不想绑定呢?哈哈,下面就是介绍这种情况。
非绑定方法又称静态方法,简单来说,就是该方法既不绑定给类,也不绑定给对象,对象和类都可以调用。在python中,为了实现这样的功能,在该方法定义时添加了@staticmethod
装饰器,下面我们通过代码进行演示:
class People():
def __init__(self, name, age):
self.name = name
self.age = age
self.id = self.create_id()
@staticmethod
def create_id():
import uuid
return uuid.uuid4()
# 对象调用
obj = People('tom', 19)
res=obj.create_id() # obj.create_id(obj)
print(res)
# 类调用
print(People.create_id())
'''
非绑定方法:静态方法
1. 加一个装饰器:@staticmethod
2. 函数已经变成普通函数
3. 对象和类都可以调用,
'''
隐藏属性
隐藏属性并不是完全的不能用,而是对于类内部可以使用,外部不可以使用而已。
如果要对类中的属性进行隐藏,只需要在给该属性前面添加双下划线,即__属性名
,这样对外就不能直接拿到该属性,但是可以通过_类名__属性名
来拿到该属性,但是一般不会这样做,一般会通过定义一个接口来访问这些属性。下面通过代码来进行演示:
class Student():
__country = 'CHINA' # 并不是完全隐藏,只是做出了改变而已,在__dict__中存为_Student__country
def __init__(self, name, age):
self.__name = name # _Student__name
self.age = age
def __func(self): # _Student__func
print('from func')
def get_country(self):
return self.__country # self._Student__country
def set_country(self, v):
if not type(v) is str:
print('不是str')
return
self.__country = v
print(Student.__dict__)
"""
注意:
1.在类定义阶段发生变形:_类名__属性名
2.类属性和对象属性都可以隐藏
3.隐藏是对内不对外,一般通过在类内部开放接口返回隐藏属性值,可以对外部做严格控制
"""
property装饰器
property装饰器的目的是为了将函数伪装成属性,调用的时候,可以不用加括号就可以调用。
class Student():
__country = 'CHINA' # _Student__country
def __init__(self, name, age):
self.__name = name # _Student__name
self.age = age
def __func(self): # _Student__func
print('from func')
# 把函数伪装成属性,但是只能查看,不能进行其他操作
@property
def country(self):
return self.__country # self._Student__country
# 实现修改该属性
@country.setter
def country(self, v):
if not type(v) is str:
return
self.__country = v
# 实现删除该属性
@country.deleter
def country(self):
print('不能删')
del self.__country
stu = Student('mary', 18)
print(stu.country)
stu.country = 'xxx'
del stu.country