一、绑定方法与非绑定方法
类中定义的函数分为两大类:
绑定方法和非绑定方法
1.绑定方法
其中绑定方法又分为:
绑定到对象的对象方法
、绑定到类的类方法
在类中直接定义的函数默认是绑定到对象的,
而为某个函数加上装饰器@classmethod后
,该函数就绑定到了类。
'''1.绑定给对象的方法'''
class Student():
school = '北京大学'
# 绑定给对象的
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
'''绑定给对象来调用的'''
def tell_info(self, username, password):
print(f"'name':{self.name} 'age':{self.age} 'gender':{self.gender},{username} {password}")
'''默认情况下,类在内部写方法是绑定给对象的,就由对象来调用,就会自动来传递参数'''
'''默认情况下,类中直接定义的函数就是默认绑定给对象的,类要调用就需要传入该方法对应需要传递的参数,方法上面有些几个参数就传递几个'''
# 实例对象就会直接生产一个对象,因为默认绑定对象的,故不需要传递自身
stu = Student('jack', 18, 'male')
print(stu.name) # jack
# 如何调用方法,对象来调用就对象来
'''
绑定给对象的方法有什么特殊之处:对象来调用方法,会把对象自己当成一个参数
传递给方法的第一个形参
'''
stu.tell_info('chen', 123) # 其实相当于 stu.tell_info(stu,'chen',123)
'''
绑定给对象的方法,也可以用类来调用,但是需要传入方法相对应需要的几个参数,
也会包括self形参也是需要自己传递过来
'''
Student.tell_info(stu, 'chen', 123)
'''绑定给类的方法'''
class Mysql():
# 传递给对象调用的
def __init__(self, ip, port):
self.ip = ip
self.prot = port
'''
被@classmethod修饰的方法,默认会绑定给类,类调用就会把类自动当成第一个参数
传递给方法的第一个形参cls
对象也可以调用并且会自动将产生该对象的类当做第一个参数传入
条件:
1.加上一个装饰器@classmethod
2.把方法的第一个形参改为cls
3.外部调用该方法的时候使用类来调用即可
4.绑定给类的方法中没有self这个参数了
5.绑定给对象的方法中,就没有cls这个参数了
'''
@classmethod
def from_func(cls): # cls就是类
return cls('127.0.0.1',3306)
# 实例对象
obj = Mysql('127.0.0.1', 3306)
print(obj.ip,obj.prot) # 127.0.0.1 3306
# 类调用方法
print(Mysql.from_func().ip) # 127.0.0.1
print(Mysql.from_func().prot) # 3306
# 对象调用
print(obj.from_func().ip) # 127.0.0.1
print(obj.from_func().prot) # 3306
2.非绑定方法(静态方法static)
'''非绑定方法(静态方法static)'''
class Student():
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
self.random_id = self.create_id()
'''
当你的方法(函数)中即不要对象绑定,也不要类绑定的时候,就可以把方法
设置为静态方法,类能调用,对象也能调用,而且不需要传任何参数
静态方法简单理解为之前一样正常的函数,如果这个函数中形参,那么类或对象调用就需要传参
'''
@staticmethod
def create_id():
import uuid
# uuid.uuid4()随机生成16位数
# 只要是生成固定的随机数,理论上就会有重复的几率
return uuid.uuid4()
def fun(self):
'''如果你在方法中即需要对象,也需要类,就把方法绑定给对象'''
print(self.__class__.__name__) # 返回该对象类的名字,以字符串形式
print(self.__class__) # 返回该对象的类
return self.__class__('chen',20,'male') # 相当于Student()
stu = Student('jack',18,'male')
# 对象直接调用静态方法
print(stu.random_id) # 这里是给init中设定了一个id
print(stu.create_id())
# 类直接调用静态方法
print(Student.create_id())
# 这里直接对象调用
stu.fun()
print(stu.fun().name)
二、私有(隐藏)属性和私有方法
'''
隐藏属性:
1.隐藏属性在类的定义阶段发生了变形:_类名.__属性名
2.隐藏属性在类的外部理论上是取不到的,但是非要取也是可以取到,
但是在类的外部取隐藏之后的属性不是目的
3.类属性、类方法、对象属性都额可以被隐藏
4.隐藏属性对外不对内
5.为什么要隐藏?
就是可以对修改类内部的属性的时候,可以在类的内部做更好的限制,
然后再类的内部开放一个公共的接口,对外返回内部隐藏的值
'''
class Student():
# 隐藏的类属性
__country = 'China' # _Student__country
__school = '哈佛大学'
'在类中隐藏属性对外不对内,所以开辟一个接口来调用'
def func(self):
return self.__country
@staticmethod # 隐藏的静态方法
def __index(): # _Student__index
print('hello index')
'在类中隐藏方法对外不对内,所以开辟一个接口来调用'
@staticmethod
def jk():
Student._Student__index()
'调用隐藏school的接口'
def get_school(self):
return self.__school
'给调用隐藏接口的修改值设定一个判断'
def set_school(self,v):
if type(v) is str:
self.__school = v
else:
print('修改的数据必须是字符串形式')
# 查询类的名称空间
# print(Student.__dict__) # 发现country发现了变形'_Student__country': 'China'
# 实例对象
stu = Student()
'''
变形后的数据目的也不是让在外部使用的,但是能在类的外部使用
这种是强制取的,这种方法不可取
'''
print(stu._Student__country) # China 在外部取类内隐藏的属性
print(Student._Student__country) # China 在外部取类内隐藏的属性
stu._Student__index() # hello index 在外部取类内隐藏的方法
Student._Student__index() # hello index
'''这种是通过类内部的公共的接口来调用隐藏类的数据属性,是可取的'''
print(stu.func()) # China
print(Student.func(Student)) # China
'''通过类内部的公共的接口调用隐藏类的方法'''
stu.jk() # hello index
Student.jk() # hello index
'在类的内部开放一个公开的接口让类外调用隐藏属性'
print(stu.get_school()) # 哈佛大学
stu.set_school('北京大学')
print(stu.get_school()) # 北京大学
# 可以做着判断
stu.set_school(132) # 判断不是字符串输出的
三、property装饰器
property装饰器的作用就是把类体内方法伪装成类属性来使用
这里的伪装的含义就是将原本需要加()的类方法不用加括号就可以直接获取结果
'''
property装饰器是一个内置的装饰器
主要是用来把类体内方法伪装成属性来使用
'''
'''第一种形式,使用类内部接口调用修改、删除、查看school数据值'''
class Student():
__school = '哈佛大学'
def get_school(self):
return self.__school
def set_school(self,v):
if type(v) is str:
Student.__school = v
else:
print('修改的数据必须是字符串形式')
def del_school(self):
del Student.__school
stu = Student()
print(stu.get_school()) # 哈佛大学
stu.set_school('北京大学')
print(stu.get_school()) # 北京大学
stu.del_school() # 删除school数据
print(stu.get_school()) # 查看类中显示没有school这个数据了
print('============')
'''第二种形式,通过装饰器,也是实现了第一种方式的所有功能,并且做了伪装'''
class Student():
__school = '哈佛大学'
@property
def school(self):
return self.__school
@school.setter
def school(self,v):
if type(v) is str:
Student.__school = v
else:
print('修改的数据属性得是字符串形式')
@school.deleter
def school(self):
del Student.__school
stu = Student()
print(stu.school) # 哈佛大学
stu.school = '北京大学'
print(stu.school) # 北京大学
del stu.school
print(stu.school)
print('============')
'''第三种形式也是用装饰器,但是可以让他不伪装,随便使用什么函数名'''
class Student():
__school = '哈佛大学' # 隐藏数据属性
def get_school(self):
return self.__school
def set_school(self, v):
if type(v) is str:
Student.__school = v
else:
print('修改的数据必须是字符串形式')
def del_school(self):
del Student.__school
'''有顺序要求'''
# 这个变量名也是随便命名的
school = property(get_school, set_school, del_school)
stu = Student()
print(stu.school)
stu.school = '北京大学'
print(stu.school)
del stu.school
print(stu.school)
'''
拓展了解
体质指数(bmi) = 体重(kg) ÷ 身高^2(米)
'''
class People():
def __init__(self, height, weight):
self.height = height
self.weight = weight
@property # 装饰器property作用是把类体功能伪装成属性来使用
def bmi(self):
return self.weight / (self.height ** 2)
jck = People(1.8, 62)
print(jck.bmi) # 19.1358024691358