Python基础_Day13
1.听写
借助封装和继承
Tiger(老虎)属性:品种 年龄 性别行为:吃饭
Cat(猫)属性:昵称 品种 年龄 性别行为:吃饭 爬树
创建对象:东北虎 2 雌---调用吃饭的行为---打印东北虎吃肉妮妮 加菲猫 1 雄---调用吃饭的行为---打印妮妮吃鱼调用爬树的行为---打印妮妮在树上
class Animal:def __init__(self, brand, age, sex):self.__brand = brandself.__age = ageself.__sex = sexdef eat(self):print("吃饭")
'''
隐藏起来的内容只有在当前类中可以使用 出了当前类没有任何意义
想对外提供 只能提供获取或者设置的方法
'''def get_brand(self):return self.__brandclass Cat(Animal):def __init__(self, brand, age, sex, name):super().__init__(brand, age, sex)self.__name = namedef eat(self):print("%s在吃鱼" % self.__name)def climb(self):print("%s在树上" % self.__name)class Tiger(Animal):def __init__(self, brand, age, sex):super().__init__(brand, age, sex)def eat(self):print("%s在吃肉" % self.get_brand())from listen.cat_tiger import *
def main():#创建一个老虎对象tiger = Tiger("东北虎", 2, "雌")tiger.eat()#创建一个猫的对象cat = Cat("加菲猫", 1, "雄", "妮妮")cat.eat()cat.climb()if __name__ == "__main__":main()
2.今日课堂概述
1.继承体系中__slots__的使用
2.多继承与多层继承中子类的继承顺序与如何调用多个父类中的构造方法
3.get/set方法属性化
4.运算符系统方法重写
5.类属性和类方法
6.动态语言与静态语言
7.深拷贝与浅拷贝
8.常用系统属性__name____dict____bases__
3.继承体系中slots的使用
__slots__限制不让对象随意的动态添加属性--->[限制只会限制当前类]
如果在继承体系中:父类中做了限制 在子类中没有设置slots的字段值 这种限制对应子类无效想让子类也有限制作用 需要在子类中把slots这个字段声明 是在父类的基础上进行添加
class Animal:__slots__ = ("brand", "age")def __init__(self, brand, age):self.brand = brandself.age = ageclass Dog(Animal):__slots__ = ("name")def __init__(self, name, brand, age):self.name = namesuper().__init__(brand, age)self.sex = "雄" # 错误# 调用打印方法时 打印对象的引用变量def __str__(self):return "Dog name:%s brand:%s age:%d" % (self.name, self.brand, self.age)from slots_pack.animal import *
def main():# 创建一个dog对象dog = Dog("旺财", "二哈", 2)print(dog)if __name__ == "__main__":main()
4.多继承与多层继承中子类的继承顺序与如何调用多个父类中的构造方法
多继承与多层继承中子类的继承顺序 ---> 采用广度继承制度这种状态的查看时机是子类没有从父类中继承任何属性 但是确实是存在继承关系
可以从类名.mro() ---> 查看当前类的继承体系
类名.__bases__ ---> 查看的是直接父类
class Animal:def __init__(self):print("动物祖宗初始化方法")class Mammal(Animal):def __init__(self):print("哺乳类")super().__init__()class Runnable(Animal):def __init__(self):print("爬行类")super().__init__()class Dog(Mammal, Runnable):def __init__(self):print("底层子类")super().__init__()res = Dog.mro()
print(res)
'''
[<class '__main__.Dog'>, <class '__main__.Mammal'>, <class '__main__.Runnable'>, <class '__main__.Animal'>, <class 'object'>]
底层子类
哺乳类
爬行类
动物祖宗初始化方法
'''如何调用多个父类中的构造方法如果多个父类中有属性需要子类继承 子类该如何调用父类的__init__方法父类类名.__init__(self, 父类需要的属性列表)
class Father:def __init__(self,name,sex):print("父亲")self.name = nameself.sex = sexclass Mother:def __init__(self, love):print("母亲")self.love = loveclass Son(Father, Mother):def __init__(self, name, love, sex):# 父类类名.__init__(self, 父类参数列表)Father.__init__(self, name, sex)Mother.__init__(self, love)
5.get/set方法属性化
封装之后 外界想获取属性值:
提供get方法 ---> 调用方法才可以获取属性值
封装之后 外界想设置属性值:
提供set方法 ---> 调用方法在方法中传递数据
属性化 —> 将调用方法的格式 转化为 类似于普通属性的获取方式
将get方法属性化的方式在get方法上 添加装饰器 @property调用方法时 可以只写方法名 不用添加小括号 自动将方法进行调用值 = 对象.get方法名
注意:如果没有添加@property装饰器 就是一个普通的方法 调用的时候必须添加小括号将set方法属性化的方式set属性化的装饰器 是在对应的get方法的基础上衍生来的@get方法名.setter属性化之后 调用就类似与普通属性那样使用等号来进行赋值对象.set方法名 = 值
注意:如果没有添加@get方法名.setter装饰器 就是一个普通的方法 调用的时候必须添加小括号 并在小括号中赋值class Person:__slots__ = ("name", "__age", "__sex")def __init__(self, name, age, sex):self.name = nameself.set_age = ageself.set_sex = sex@propertydef get_age(self):return self.__age@get_age.setterdef set_age(self, age):if age < 0:self.__age = 0else:self.__age = age@propertydef get_sex(self):return self.__sex@get_sex.setterdef set_sex(self, sex):if sex in ("男", "女"):self.__sex = sexelse:self.__sex = "男"def __str__(self):return "Person name:%s age:%d sex:%s" % (self.name, self.__age, self.__sex)__repr__ = __str__from set_get_property.person import Person
def main():# 创建人的对象person = Person("杨阳", 18, "女")print(person)# 获取这个对象的名字name = person.nameprint(name)# 将get方法进行属性化 调用方法的时候 不使用小括号来调用 直接把方法名当做普通的属性来进行使用 sex = person.get_sexprint(sex)# 获取年龄age = person.get_ageprint(age)# 赋值# 给name进行重新赋值person.name = "羊羊羊"print(person)# 将set方法属性化之后 调用的时候直接调用方法名即可 赋值的时候 用类似于普通属性那种等号赋值方式赋值即可person.set_sex = "男"print(person)# 修改年龄person.set_age = 20print(person)if __name__ == "__main__":main()
6.运算符系统方法重写
字符串:+*>=<=><==!=%class Pointer:def __init__(self, pass_x, pass_y):self.x = pass_xself.y = pass_ydef __add__(self, other):# self + othernew_x = self.x + other.xnew_y = self.y + other.ynew_p = Pointer(new_x, new_y)return new_pdef __mul__(self, value):# self * valueself.x = self.x * valueself.y *= 5return selfdef __eq__(self, other):#self == otherif self.x == other.x and self.y == other.y:return Trueelse:return Falsedef __ne__(self, other):#self != otherif self.x != other.x or self.y != other.y:return Trueelse:return Falsedef __ge__(self, other):#self >= otherif self.x >= other.x or self.y >= other.y:return Trueelse:return Falsedef __le__(self, other):#self <= otherif self.x <= other.x or self.y <= other.y:return Trueelse:return Falsedef __gt__(self, other):# self > otherif self.x > other.x or self.y > other.y:return Trueelse:return Falsedef __lt__(self, other):#self < otherif self.x < other.x or self.y < other.y:return Trueelse:return Falsedef __mod__(self, value):#self % valueself.x %= valueself.y %= valuereturn selfdef __str__(self):return "Pointer x:%d y:%d" % (self.x, self.y)__repr__ = __str__p1 = Pointer(1, 2)
print(id(p1))
print(p1)
p2 = Pointer(1, 2)
print(id(p2))
# 将两个点的坐标相加 生成一个新的点的对象
res = p1 + p2
print(res)
print(id(res))# 乘法 可以乘以一个数值n 将原有的对象的坐标点的值 坐标值是原有基础上数值n的倍数
res =p1 * 5
print(id(res))
print(res)# 如果不重写 对应的方法 默认比较是地址
print(p1 == p2)
print(p1 == res)# 进行重写 比较坐标点 一样返回True
p3 = Pointer(2, 4)
p4 = Pointer(2, 4)
print(p3 == p4)
使用比较多的
__eq__(self, other):
如果不重写 默认比较的是地址
重写的话一般是判定伪相等 只要两个对象满足某些需求 就判定两个对象相等
例如: 在程序中有一个人类属性: 身份证号现在有两个人类对象 以现实生活需求判定 这两个对象是否是同一个人只要两个对象的身份证号一致 视为同一个人
class Person:def __init__(self, cardid, name):self.name = nameself.cardid = cardiddef __eq__(self, other):#self == otherif self.cardid == other.cardid:return Trueelse:return Falsep1 = Person(100001, "张三")
p2 = Person(100001, "李四")
p3 = Person(100002, "张三")
print(p1 == p2) # True
print(p1 == p3) # False
7.类属性和类方法:
对象属性在创建对象的时候 self后面的变量名就是对象属性被包含在__init__方法中的
类属性直接被包含在类体中 与其他方法是平级的什么时候使用类属性?当该类所有对象的某个属性的值一致时 就可以将其提为类属性 类属性是被该类所有对象所共享的 类属性是属于类的 被加载到方法去中 只要是该类对象 就具有了该属性使用的时候 可以使用对象进行调用 也可以使用类进行调用 建议使用类进行调用
案例:
人类:name agesexcountry[国籍] ---> 所有人的国籍都是CH
class Person:__slots__ = ("name", "age", "sex")__country = "CH"def __init__(self, name, age, sex):self.name = nameself.age = ageself.sex = sex@classmethoddef get_country(cls):print(cls)return cls.__countrydef __str__(self):return "Person name:%s age:%d sex:%s country:%s" % (self.name, self.age, self.sex, self.__country)__repr__ = __str__from class_property_method.person import Person
def main():p1 = Person("张三", 20, "男")p2 = Person("李四", 21, "男")p3 = Person("王五", 22, "女")print(p1)print(p2)print(p3)print(Person.get_country())print(p1.get_country())if __name__ == "__main__":main()
'''
Person name:张三 age:20 sex:男 country:CH
Person name:李四 age:21 sex:男 country:CH
Person name:王五 age:22 sex:女 country:CH
<class 'class_property_method.person.Person'>
CH
<class 'class_property_method.person.Person'>
CH
'''对象方法:特点: 方法的第一个形参为self ---> 表示的是调用方法的对象调用该方法通过对象来调用
类方法:需要装饰器 @classmethod 将方法装饰成类方法类方法的第一个形参: cls ---> 表示的是当前类这个参数与self类似 不需要手动传值 通过类或者对象调用时 会自动将其类型赋值给cls什么时候使用类方法?类方法一般是操作类属性的类属性和类方法建议使用类来进行调用
静态方法[了解]需要使用装饰器 @staticmethod 将方法装饰成静态方法静态方法中的形参个数是根据需求来确定的 没有多余的类似于对象方法的self 和 类方法的cls 一般来使用的话 也是通过类名来进行调用该
练习:
学生类:nameagesexcount ---> 学生个数
要求:创建n个学生对象 统计学生个数不管用哪个学生对象调用个数 个数都是一致的
例如:s1 = s2 = s3 = print(s1.count) # 3
如何检测对象被创建了 ---> init
class Student:__stu_count = 0def __init__(self, name, age, sex):self.name = nameself.age = ageself.sex = sex# 这个方法可以检测对象是否创建Student.__stu_count += 1@classmethoddef get_count(cls):#print(self.name)return cls.__stu_count@staticmethoddef show_info(info):print("这是一个静态方法")if __name__ == "__main__":s1 = Student("小明", 17, "男")s2 = Student("小刚", 16, "男")s3 = Student("小强", 18, "男")print(s1.get_count()) # 3print(s2.get_count()) # 3print(s3.get_count()) # 3Student.show_info("内容") # 这是一个静态方法res = Student.get_count() # 3print(res)
注意:
在类方法中不允许出现self
原因:类方法加载的时候还没有对象 就不能使用与对象相关的内容
从创建对象的过程:p = Person("小明", 12, "男")
内存中的变化:1. 将Person类加载到方法区内存中跟随者一起加载到内存中的有 类属性和类方法2.在对中开辟一块内存 存放该类声明的对象 并产生一个地址跟随者加载的有对象属性3. 将创建对象是传递的数据 给对象属性进行初始化4. 将对象的地址 赋予给变量p
8.静态语言和动态语言
静态语言:
声明变量时 必须先声明出该变量的类型 给变量赋值的时候 只能赋予该类型的数据java
动态语言:
变量的类型是根据赋值来决定的Python属于动态语言 --- 本身就是多态的变量赋予什么类型的数据 展现就是对应的类型class Pet:def __init__(self, name, age, sex, power):self.name = nameself.age = ageself.sex = sexself.power = powerclass PetDog(Pet):def __init__(self, name, age, sex, power):super().__init__(name,age,sex,power)def look_home(self):print(self.name, "在看家")class PetCat(Pet):def __init__(self, name, age, sex, power):super().__init__(name, age, sex, power)def catch_mouse(self):print(self.name, "抓老鼠")class Host:def __init__(self, name):self.name = name# 根据不同的场景 随时切换不同的类型 这个就是多态def introduce(self, pet):# 如何判断变量接受的是什么类型if isinstance(pet, PetDog):print("我家狗叫%s, %d岁了, 会%s" % (pet.name, pet.age, pet.power))elif isinstance(pet, PetCat):print("我家猫叫%s, %d岁了, 会%s" % (pet.name, pet.age, pet.power))from polymorphic.pet import *
def main():dog = PetDog("旺财", 2, "雌", "两条腿走路")cat = PetCat("加菲", 2, "雄", "装死")host = Host("baby")host.introduce(dog)host.introduce(cat)if __name__ == "__main__":main()
9.常用字段
常用系统属性
__name__--- 类来调用 结果类的字符串名字
__dict__--- 一般常用与使用对象来调用返回的是一个字典 字典中包含的数据 { 对象属性:属性值, 对象属性:属性值}
__bases__--- 元组 包含继承的父类
class Person:def __init__(self, name, age):self.name = nameself.age = ageif __name__ == "__main__":res = Person.__name__print(type(res)) # <class 'str'>print(res) # Personp = Person("小刚", 20)res = p.__dict__print(res) # {'name': '小刚', 'age': 20}res = Person.__bases__print(res) # (<class 'object'>,)
10.深拷贝和浅拷贝
对于不可变对象 是没有拷贝这个功能的
浅拷贝:
只会拷贝最外层对象 内层对象还是引用的原来的地址
深拷贝:
内外都会生成一个新的对象 占用的地址不一样
需要借助模块 copy
import copy
# 不可变对象是没有拷贝行为的 不管如何进行操作 获取的都是原来地 地址 没有生成新的对象
str0 = "abc"
print(id(str0)) # 2445453913424
# 对其进行浅拷贝
res = copy.copy(str0)
print(id(res)) # 2445453913424
# 对其进行深拷贝
res = copy.deepcopy(str0)
print(id(res)) # 2445453913424class Person:def __init__(self, name):self.name = namedef __str__(self):return "Person name:%s" % self.name__repr__ = __str__# 可变对象的拷贝行为
person = Person("小黄")
print("人类对象的地址:",id(person)) # 人类对象的地址: 2445454886728list0 = ["abc", True, 10, person]
print("原列表中引用的人类对象的地址",id(list0[3])) # 2445454886728
print("原列表地址:", id(list0)) # 2445456412488# 浅拷贝 将最外层对象拷贝出来一个新的对象 但是内部的其他对象引用还是原来的地址
new_list = copy.copy(list0)
print(new_list)
print("浅拷贝出来的新列表的地址:", id(new_list)) # 2445456411080
print("浅拷贝出来的新列表引用的人类对象的地址:", id(new_list[3])) # 2445454886728# 深拷贝: 内外对象都会拷贝出来一个新的对象
deep_list = copy.deepcopy(list0)
print(deep_list)
print("深拷贝出来的新列表的地址:", id(deep_list)) # 2445456412496
print("深拷贝出来的新列表引用的人类对象的地址:", id(deep_list[3])) # 2445454886896
'''
列表的方法中 提供了浅拷贝的方法
凡是可变对象的 都提供了一个浅拷贝的方法
'''
Python基础_Day13相关推荐
- f是一个python内部变量类型,Python基础变量类型——List浅析
Python使用list 一.list Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时添加和删除其中的元素. 比如,列出班里所有同学的名字,就可以用一个list表示 ...
- python 等号报错_Python学习----Python基础
Python基础 一.数据类型和变量 1.在Python中,等号=是赋值语句,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量. 例如: a =520# a是整数prin ...
- python基础——继承与派生、组合
python基础--继承与派生 1 什么是继承: 继承是一种创建新的类的方式,在python中,新建的类可以继承自一个或者多个父类,原始类成为基类或超累,新建的类成为派生类或子类 1.1 继承分为:单 ...
- Python学习笔记1 Python基础
第1章 Python基础 1.1 Python概述及版本介绍 1.Python是一种面向对象的解释型计算机程序设计语言(解释型语言源代码->解释器逐行解释每一句源代码) 2.优点:高级语言.可移 ...
- python基础---元组、字典、函数、文件、异常
文章目录 python基础---元组.字典.函数.文件.异常 Tuple(元组) 常用操作 dict(字典) 函数 文件 异常 python基础-元组.字典.函数.文件.异常 Tuple(元组) tu ...
- 快速掌握Python的捷径-Python基础前传(1)
文: jacky(朱元禄) 开文序 最近看新闻,发现高考都考Python了,随着人工智能的火热,学数据科学的人越来越多了!但对于数据行业本身来说,现象级的火热,这并不是什么好事. 方丈高楼平地起,无 ...
- Python培训教程之Python基础知识点梳理
Python语言是入门IT行业比较快速且简单的一门编程语言,学习Python语言不仅有着非常大的发展空间,还可以有一个非常好的工作,下面小编就来给大家分享一篇Python培训教程之Python基础知识 ...
- python基础04
python基础04 python2在编译安装时,可以通过参数 -----enable----unicode=ucs2 或 -----enable--unicode=ucs4 分别用于指定使用2个字节 ...
- 刻意练习:Python基础 -- Task12. 模块
背景 我们准备利用17天时间,将 "Python基础的刻意练习" 分为如下任务: Task01:变量.运算符与数据类型(1day) Task02:条件与循环(1day) Task0 ...
- 刻意练习:Python基础 -- Task11. 魔法方法
背景 我们准备利用17天时间,将 "Python基础的刻意练习" 分为如下任务: Task01:变量.运算符与数据类型(1day) Task02:条件与循环(1day) Task0 ...
最新文章
- 计算机二年级考试word,计算机二年级MSOffice真题.docx
- 实现entity、dao 、service 、serviceImpl自动生成
- Qt Creator分析QML应用程序
- android 限制edittext 最大输入字符数
- jsp需要多少java基础_Java基础——JSP(一)
- C语言嵌入式系统编程修炼之内存操作
- 控件的WM_NOTIFY消息映射
- 壁纸控的你需要看这里!
- 微信小程序wx.navigateTo无法跳转
- RS-485通信协议(ModBus版)
- 淘宝千万级并发架构的十四次演进
- linux和windows php pdf转图片,扩展安装imagick和ImageMagick
- Avaya Aura™ 独家观察报告
- Gromacs基础教程一:入门建议
- Access violation at address 77106D4E in module 'ntdll.dll'. Write of address 004051A5.
- 数理统计——描述统计与Python实现
- 致这一段无悔的大学青春
- 注册表 关闭打印机服务器,Win7系统添加打印机无Print Spooler服务无注册表解决方法...
- 从字节跳动提前批来看今年校招形势
- 最详细PicGo(图床)加阿里云OSS实现图片自动上传