python基础day32 面向对象绑定方法和隐藏属性
绑定方法
绑定给对象的方法
class Student(): school = 'SH' def __init__(self, name, age, gender): # self:对象自己 self.name = name self.age = age self.gender = gender ''' 这就是绑定给对象的方法, 特殊之处:1. 函数的第一个形参self是对象自己 2. 绑定给对象的方法就有对象来调用,他会把对象自己当成第一个参数传给方法的第一个形参 ''' def tell_info(self): # self:也是对象自己 print("name:%s, age:%s, gender:%s" % (self.name, self.age, self.gender)) stu = Student('kevin', 18, 'male') ''' 绑定给对象的方法目的不是想让类来调用的,但是类也能调用,只不过方法里面有几个参数就要传几个参数
绑定给类的方法
# ip:127.0.0.1 port:3306 ====> ip+port可以唯一确定一台计算机上的一款软件 class Oracle(): def __init__(self, ip, port): self.ip = ip self.port = port @classmethod # 该方法已经变成了绑定给类的方法,而不是绑定给对象了 def from_func(cls): # self:就是类名 print("from func") # return Oracle(settings.IP, settings.PORT) return cls(settings.IP, settings.PORT) obj = Oracle('127.0.0.1', 3306) # print(obj.ip) # print(obj.port) # res=obj.from_func() # Oracle.from_func(Oracle) res=Oracle.from_func() # from func 绑定给类的方法就有类来调用,特殊之处就是:会把类名当成第一个参数传给方法的第一个形参 print(res)
非绑定方法
就是不绑定给类使用,也不绑定给对象使用
静态方法:static
补充:uuid
import uuid """只要随机串的长度一定,理论上,只要次数足够多,就一定会出现重复的可能""" print(uuid.uuid4()) # 65f1ff6b-dd39-441a-8788-0dfde07d6922 class Student(): def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender # self.id = self.create_id() self.id = self.get_code(5) @staticmethod # 该方法已经谁都不绑定,谁都能来调用,类和对象都可以直接来调用,其实就是个普通方法 def create_id(): import uuid return uuid.uuid4() """什么时候使用静态方法:一般就是方法里面既不用对象,也不用类的时候就使用静态方法""" @staticmethod def get_code(n): code = '' import random for i in range(n): random_int = str(random.randint(0, 9)) random_upper = chr(random.randint(65, 90)) random_lower = chr(random.randint(97, 122)) # temp = random.choice(random_int,random_upper,random_lower) # temp = random.choice[random_int,random_upper,random_lower] temp = random.choice([random_int, random_upper, random_lower]) code += temp return code """如果说方法里面及用到了对象,又用到了类,方法绑定给谁更合适?""" def func(self): print(self) print(self.__class__.__name__)
# 优先绑定给对象 stu = Student('kevin', 19, 'female') # stu1 = Student('kevin1', 19, 'female') # print(stu.id) # print(stu1.id)
隐藏属性
1. 隐藏属性在类的定义阶段发生了变形,_类名__属性名
2. 不但可以隐藏类属性,方法、对象的属性都可以隐藏
3. 隐藏属性对外不对内,对类的外部是隐藏的,而对类的内部是开放的
如何隐藏
class Student(): # '_Student__school': 'SH' _类名__属性名: 'SH' # school = 'SH' # 把school属性已经隐藏了,隐藏的意思是,在类外部不能使用了 __country = 'China' def __init__(self, name, age, gender): self.__name = name # _Student__name self.age = age self.gender = gender def __func(self): # _Student__func _类名__函数名 print('from func') # def index(self): # return self.__school # self._Student__school def get_country(self): return self.__country def set_country(self, v): if type(v) is not str: return Student.__country = v stu = Student('kevin', 19, 'male') # print(stu.__school) # 查看类的名称空间 print(Student.__dict__) print(stu.__school) # 变形之后的数据目的不是想让我们在外部使用的, 但是在类的外部也能使用 print(stu._Student__school) # SH stu._Student__func() print(stu.name) print(stu._Student__name) res=stu.index() print(res) # SH
为什么要隐藏
由于隐藏属性是对外不对内的,所以,我们要想在类的外部使用,就需要在类的内部开放一个接口,返回隐藏属性的值,以便更好的对外限制
property装饰器
作用:就是把方法伪装成属性来使用
如何伪装
方式一
class Student(): __country = 'China' __city = 'shanghai' def __init__(self, name, age, gender): self.__name = name # _Student__name self.age = age self.gender = gender @property def country(self): return self.__country @country.setter def country(self, v): if type(v) is not str: return Student.__country = v @country.deleter def country(self): print("可以删除了") del Student.__country @property def city(self): return self.__city @city.setter def city(self, v): Student.__city = v @city.deleter def city(self): print("可以删除了") del Student.__city stu = Student("kevin", 20, 'female') # print(stu.get_country()) print(stu.country) stu.country = 'Japan' print(stu.country) del Student.country stu.set_country('Japan') del stu.country
方式二
class Student(): __country = 'China' __city = 'shanghai' def __init__(self, name, age, gender): self.__name = name # _Student__name self.age = age self.gender = gender def get_country(self): return self.__country def set_country(self, v): if type(v) is not str: return Student.__country = v def del_country(self): print("可以删除了") del Student.__country """这种方式,是有顺序要求的""" country = property(get_country, set_country, del_country) stu = Student("kevin", 19, 'male') print(stu.country) # stu.country = 'Japan' # print(stu.a) # del stu.country
练习
如何计算人的bmi指数
class Bmi(): def __init__(self, weight, height): self.weight = weight self.height = height @property def bmi(self): return self.weight / (self.height ** 2) bmi = Bmi(70, 1.8) print(bmi.bmi)
面对对象的三大特征
封装:也是一种思想,把冗余的代码、重复的代码都封装成函数,以后都调用函数来用
继承:
1. 什么是继承:
继承就是新建类的一种方式,新建出来的类称为是子类或者叫派生类,被继承的类称为父类或者是基类
子类可以继承父类的所有属性和方法
2. 为什么要继承?
类解决什么问题:解决的是对象与对象之间的代码冗余问题
继承解决什么问题:解决的是类与类之间的代码冗余问题
3. 怎么样继承?
新式类:继承了object类的子子孙孙类都是新式类
经典类:没有继承object类的子子孙孙类都是经典类
只有在python2中才区分经典类和新式类,python3中都是新式类
class Parent1(object): pass class Parent2: pass # 直接把类名写在括号里就是继承,括号里面写的类是父类,括号外的是子类 class Sub1(Parent1): pass # python中支持多继承, 括号里面可以写多个类 class Sub2(Parent1, Parent2): pass # 如何查看一个类继承了哪些父类? print(Sub1.__bases__) print(Sub2.__bases__) print(Parent1.__bases__) # object
# 以学生选课系统为例 class People(): school = 'SH' # 严格依赖继承 def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender class Student(People): def __init__(self, name, age, gender, course): """这个是指名道姓的调用方法,不依赖于继承""" People.__init__(self, name, age, gender) # 有什么特殊之处, self.course = course def choose_course(self): pass stu = Student('kevin', '19', 'male', 'python') # 对象属性的查找顺序:先从对象自己的名称空间查找,如果找不到,再去类中取查找,如果找不到,取继承的父类转中查找, print(stu.school) print(stu.name) class Teacher(People): def __init__(self,name, age, gender, level): People.__init__(self, name, age, gender) # 有什么特殊之处, self.level = level def score(self): pass tea = Teacher("ly", 20, 'female', 10) print(tea.school) 多态