文章目录
- 知识点
- 1.私有属性与私有方法
- 1.私有属性
- 2.私有方法
- 2.成员
- 3.实例属性
- 1.类属性(静态属性)
- 2.属性总结
- 4.实例方法
- 5.类方法
- 6.静态方法
- 7.封装介绍
- 8.继承(重点)
- 9.新式类与经典类
- 练习
- 10.单继承
- 1.super()
- 练习
- 11.作业
知识点
- 私有属性与私有方法
- 成员
- 属性
- 方法
- 封装
- 继承
- 多态
1.私有属性与私有方法
在实际开发中,对象的某些属性或者方法,只希望在对象的内部使用,这时,我们就可以使用私有属性和私有方法。
1.私有属性
- 私有属性:就是对象不希望公开的属性
- 定义方式:在属性名前面增加两个下划线(例如:__name)
练习
- 定义类为:"人"类
- 创建对象:rose
- 初始化对象属性:name 与 age
- 要求:age 不能在类的外部访问
class Human:def __init__(self):self.name = 'rose'# 两个下划线,则为私有属性self.__age = 18# 报错:因为定义为私有属性,则在外部无法访问# AttributeError: 'Human' object has no attribute 'age'
rose = Human()
print(rose.name)
print(rose.age)
需求:一定要在类的外部访问到对象的私有属性,如何实现?
方法:
- 可以通过类的内部的方法访问私有属性
class Human:def __init__(self):self.__name = 'rose'# 两个下划线,则为私有属性self.age = 18def __str__(self):print(self.__name)
rose = Human()
rose.__str__()
- 通过类的内部方法将私有属性返回出去,在类的外部调用该方法并且接收就可
class Human:def __init__(self):self.__name = 'rose'# 两个下划线,则为私有属性def __str__(self):return self.__name
name = Human()
print(name.__str__())
2.私有方法
- 私有方法:就是对象不希望公开的方法
- 定义方式:在方法名前面增加两个下划线(例如:__test)
注意:
在 python 中,并没有真正意义上的私有,只有伪私有。当我们在访问时,以 对象._类名__私有属性 即可访问,私有方法同理。但是不建议使用。
2.成员
3.实例属性
实例属性属于对象,只能通过对象访问
- 定义:self.属性名称
- 访问:self.属性名称 或 对象.属性名称
练习:定义一个省份类,打印输出班级每位同学所在的国家与省份。
class Province:def __init__(self, country, province):self.country = countryself.province = provincedef print_def(self):print(self.country, self.province)jeff = Province('中国', '广东')
jeff.print_def() # 中国 广东
amy = Province('中国', '湖南')
amy.print_def() # 中国 湖南
1.类属性(静态属性)
类属性属于类,保存在类中。在创建时,仅创建一份,并且所有对象都共享静态属性。执行时可以是类访问也可以是对象访问。
- 定义:直接在类中定义
- 访问:类名.属性名称 或 self.属性名称 或 对象.属性名称
class Province:country = '中国' # 静态属性def __init__(self, province):self.countryself.province = provincedef print_def(self):print(self.country, self.province)jeff = Province( '广东')
jeff.print_def() # 中国 广东
amy = Province( '湖南')
amy.print_def() # 中国 湖南
2.属性总结
在实际开发中,如果属性的值是固定的,不随对象的改变而改变。那就使用静态属性(类属性),这样有利于节省内存的消耗。而如果属性的值随对象的改变而改变,就使用实例属性。
4.实例方法
普通方法保存在类中,在实例化对象后,一般通过对象调用。第一个参数必须为系统自建参数,默认为 self,代指对象本身。
class Demo:def __init__(self, name):self.name = '啊巴啊巴'def text(self):print(self.name)
d = Demo('Jeff')
d.text()
注意:
- 当需要在方法中使用实例属性时,通常使用实例方法
- self 仅仅是变量名。使用其它也可,但最好不要修改
5.类方法
类方法通过在方法上面添加@classmethod 装饰器,保存在类中;
class Abc:def abc(self):pass@classmethoddef bnc(cls): # 自建参数为cls,指当前的类pass
注意:
- 类方法不需要传入self。但有一个系统自建参数为cls,cls代指类本身;
- 类方法一般通过类调用,也可通过对象调用
6.静态方法
静态方法通过在方法上面添加 @staticmethod 装饰器定义,保存在类中;
import time
# 导入时间模块
class ShowTime:@staticmethod # 静态方法def time_1(): # 静态方法不需要传入selfprint(time.strftime('%Y:%m:%d',time.localtime()))# 2021: 01:26sj = ShowTime()
sj.time_1()
注意:
- 静态方法不需要传入self参数,即使传入了self参数也并不像普通方法那样代指对象本身,仅仅是一个普通的形参。
- 静态方法的调用虽然可以通过对象调用,但一般由类调用。
- 静态方法的参数并不代表对象这一特点,使静态方法在类中使用起来更像一个单纯的函数。完全可以将静态方法放在类的外部,当成函数使用。但是放在类中,便于使用与维
护。
7.封装介绍
封装是面向对象编程的一大特点,将属性和方法放到类的内部,通过对象访问属性或者方法,隐藏功能的实现细节,也可以设置访问权限。
class Student:def __init__(self, name, age): # 将属性封装到类的内部self.name = nameself.age = agedef print_text(self):print(self.name, self.age)
yu = Student('屿', 18)
yu.print_text() # 屿 18
# 在同一个类,创建多个对象之间互不干扰
ywyg = Student('屿我有关', 18)
ywyg.print_text() # 屿我有关 18
8.继承(重点)
继承是一种创建新类的方式,如果子类需要复用父类的属性或者方法时,就可以使用继承。当然,子类也可以提供自己的属性和方法。
class Father:pass
class Son(Father):pass
注意:
- 在 python 中,新建的类可以继承一个或多个父类
- 继承作用:避免重复造轮子,减少代码的冗余
class Father:def chi(self):print('吃')
class Son(Father):def he(self):print('喝')
jc = Son()
jc.chi() # 吃
由此可见,我调用的子类中并没有 ‘吃’ 这个代码,但是却可以在父类中继承。
9.新式类与经典类
在 Python2 当中类分为新式类和经典类,如果有继承父类 object 则是新式类,否则为经典类。
class Demo(object): # 新式类pass
class Demo: # 经典类pass
但是在 Python3 当中,全部都是新式类,默认继承 object。
练习
验证 Python3 中,全部都是新式类
实现思路:比较继承与无继承两个空类的成员是否一致拓展方法:
- 对象.dir() 查看对象的属性与方法
class Demo1:pass
class Demo2(object):pass
d1 = Demo1()
d2 = Demo2()
print(d1.__dir__())
print(d2.__dir__())
10.单继承
子类继承父类,则可以直接享受父类中已经封装好的方法
class Father:pass
class Son(Father):pass
当对象调用方法时,查找顺序先从自身类找,如果自身没找到,则去父类找,父类无,再到父类的父类找,直到object类,若还无,则报错。这也称为深度优先机制。
需要注意的是,当子类与父类拥有同名称的方法时,子类对象调用该方法优先执行自身的方法。那么实际上就是子类的方法覆盖父类的方法,也称为重写。
class Father:def shui(self):print('父亲睡')
class Son(Father):def shui(self):print('儿子睡')
son = Son()
son.shui() # 儿子睡
但是实际的开发中,遵循开放封闭原则。我们并不会完全的重写父类的方法,而是希望同时实现父类的功能。这时,我们就需要调用父类的方法了,可以通过 super()函数实现。
注意:
- __init__方法也会继承,同实例方法一致
- 私有属性以及私有方法没有被继承
1.super()
super(type[, object-or-type]) 函数是用于调用父类(超类)的一个方法
- type --> 类
- object-or-type --> 对象或类,一般是 self
练习
- 用代码实现如下:
class GrandFather:def shui(self):print('睡')
class Father(GrandFather):def chi(self):print('吃')def he(self):print('喝')
class Son(Father):def xue(self):print('学python')
son = Son()
son.xue() # 学python
son.he() # 喝
son.chi() # 吃
son.shui() # 睡
- 继以上练习实现,在Son的sleep方法当中,调用父类的sleep方法。
class Father:def shui(self):print('父亲睡')
class Son(Father):def shui(self):print('儿子睡')super().shui()
son = Son()
son.shui()
# 儿子睡
# 父亲睡
11.作业
- 作业1
玩个特别无聊的游戏,猜数字。玩家输入一个数字与计算机随机生成的数字作对比当两个值相等时,则说明用户猜对了
注意: 外部不能获取到计算机随机生成的值
import random
class GuessNumber(object):def __init__(self):self.__i = random.randint(0, 10)def guess(self):num = int(input('请输入一个0-10的整数'))# print('猜对了' if self.__i == num else '错了错了')# print(f'私有属性{self.__i}')while True:if self.__i == num:print('答对了')breakelse:num = int(input('猜的不对哦,请重新输入:'))guess_1 = GuessNumber()
guess_1.guess()
- 作业2
创建一个煎饼类 调用烹饪时长的方法累计煎饼状态 - 如果煎的时间在0-3之间则状态为生的
- 如果煎的时间在3-5之间则状态为半生不熟的
- 如果煎的时间在5-8之间则状态为全熟的
- 当时间超过8分钟状态焦了
- 并且还可以给煎饼添加作料,比如大葱(hhh),大蒜(hhh)?,烤肠等等
class Pancake(object):def __init__(self):self.pancake_time = 0self.status = '生的'self.seasoning = []def __str__(self):return f'煎饼的时间为{self.pancake_time},煎饼的状态为{self.status},加的料是{self.seasoning}'def pancake_status(self, cook_time):self.pancake_time += cook_timeif self.pancake_time >= 0 and self.pancake_time < 3:self.status = '生的'elif self.pancake_time >= 3 and self.pancake_time < 5:self.status = '半生不熟'elif self.pancake_time >= 5 and self.pancake_time < 8:self.status = '全熟'elif self.pancake_time >= 8:self.status = '焦了'def pancake_seasoning(self, seasoning):self.seasoning.append(seasoning)jianbing = Pancake()
jianbing.pancake_status(1)
jianbing.pancake_seasoning('一根香肠,两个蛋')
print(jianbing)