python基础
- 类和对象
- ⾯向对象代码的步骤
- 类的设计
- self 参数
- 魔法⽅法
- 初始化⽅法____init____
- ______str_____ ⽅法
- 封装
- 继承
- 重写(override)
- 多态
- 对象 属性 方法
- 静态方法
- 文件
- ⽂件操作
- 打开⽂件的⽅式
- json ⽂件
- 异常
类和对象
类: 是对具有相同特征或者⾏为的事物的⼀个统称, 是抽象的,不能直接使⽤
指代 多个事物
代码中 类是由关键字 class 定义
对象:是由类创建出来的⼀个具体存在的事物, 可以 直接使⽤指代 ⼀个具体事物
代码中 使⽤ 类 去创建(实例化)
类的构成, 类的三要素
1, 类名 (多个事物 起⼀个名字,标识符规则, ⻅名知意, 类名
⽤例满⾜⼤驼峰命名法(所有单词的⾸字⺟⼤写))
2, 属性 (事物的特征)
3, ⽅法 (事物的⾏为)
⾯向对象代码的步骤
1, 设计类 (找类的三要素)
2, 定义类
3, 创建对象(实例化对象)
4, 由对象调⽤类中的⽅法
类的设计
类的设计 就是找三要素. 属性和⽅法 可能会有很多,我们只需要找到关注的即可
class Cat:
def eat(self): # self 暂时不管
"""吃鱼的方法"""
print('小猫爱吃鱼...')
# 创建对象
tom = Cat()
# 通过对象 调用类中的方法
tom.eat()
self 参数
1, 参函数的语法上来看, self 是形参, 名字可以任意的变量名, 只是我们习惯性叫 self
2, 特殊点: self 是⼀个普通的参数, 按照函数的语法,在调⽤的时候,必须传递实参值, 原因, 是 Python 解释器⾃动的将 调⽤这个⽅法的对象作为参数传递给 self所以 self 就是调⽤这个⽅法对象
给对象添加属性: 对象.属性名 = 属性值 # 添加或者修改
class Cat:
def eat(self): # self 是调用这个方法的对象
"""吃鱼的方法"""
print(f'self:{id(self)}')
print(f'小猫{self.name}, {self.age}岁 爱吃鱼...')
# 创建对象
tom = Cat()
# 通过对象 调用类中的方法
print(f"tom :{id(tom)}")
# 给 Tom 对象添加 name 属性
tom.name = '汤姆'
tom.age = 3
print(tom.name)
tom.eat()
blue_cat = Cat()
print(f'blue:{id(blue_cat)}')
blue_cat.name = '蓝猫'
blue_cat.age = 4
blue_cat.eat()
魔法⽅法
在Python 中存在⼀类⽅法, 以两个下划线开头, 两个下划线结尾, 在满⾜某个条件的情况下,会⾃动调⽤, 这⼀类⽅法 称为是魔法⽅法
初始化⽅法____init____
1, 调⽤时机 在创建对象之后,会⾃动调⽤.
2, 应⽤场景 初始化对象, 给对象添加属性
3, 注意事项
- 不要写错
- 如果 属性是会变化的, 则可以将这个属性的值作为参数
传递, 在创建对象的时候,必须传递实参值
class Cat:
def __init__(self, name):
print('我是 init 方法, 我被调用了') # 验证使用,正式代码不要
self.name = name
def eat(self):
print(f"小猫 {self.name} 爱吃鱼")
# init 方法 创建对象之后 会自动调用 1 会 2 不会
# Cat # 2 不是创建对象
# Cat() # 1 因为是创建对象
# tom = Cat # 2 不是创建对象, 即 tom 也是类
# blue = Cat() # 1 创建对象
# b = blue # 2 不是创建对象, 只是引用的传递
# t = tom() # 1, tom 已经是类, 类名() 就是创建对象
blue_cat = Cat('蓝猫')
print(blue_cat.name)
blue_cat.eat()
black_cat = Cat('黑猫')
black_cat.eat()
_str ⽅法
1, 调⽤时机使⽤ print(对象) 打印对象的时候, 会⾃动调⽤
1, 如果没有定义 str ⽅法, 默认打印的是 对象的引⽤地址
2, 如果定义 str ⽅法,打印的是 ⽅法的返回值
2, 应⽤场景
使⽤ print(对象) 打印输出对象的属性信息
3, 注意事项 必须返回⼀个 字符串
class Cat:
def __init__(self, name, age):
self.name = name # 添加 name 属性
self.age = age # 添加 age 属性
def __str__(self): # 一般不使用 print,直接返回
return f"姓名: {self.name}, 年龄: {self.age}"
# 创建对象
tom = Cat('汤姆', 3)
print(tom)
print(dir(tom))
封装
封装: 根据要求将属性和⽅法 定义到类中(定义类)
class Person:
def __init__(self, name, weight):
self.name = name # 姓名
self.weight = weight # 体重
def __str__(self):
return f"{self.name} 目前的体重为 {self.weight} kg"
def run(self):
"""跑步的方法"""
# 体重减少 0.5kg
# self.weight = self.weight - 0.5
self.weight -= 0.5
print(f'{self.name} 跑步了, 体重减少 0.5 kg')
def eat(self):
"""吃东西的方法"""
# 体重增加 1kg
self.weight += 1
print(f"{self.name} 大餐一顿, 体重增加了 1kg")
if __name__ == '__main__':
# 创建对象
xming = Person('小明', 75.0)
print(xming)
xming.run()
print(xming)
xming.eat()
print(xming)
xmei = Person('小美', 45.0)
print(xmei)
xmei.run()
xmei.run()
print(xmei)
xmei.eat()
print(xmei)
继承
1, 继承描述的是类与类之间的关系 is … a
2, 继承的好处: 减少代码冗余,重复代码不需要多次书写, 提高编程效率
# 1. 定义动物类,动物有姓名和年龄属性,具有吃和睡的行为
class Animal:
"""动物类"""
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
"""吃"""
print(f'{self.name} 吃东西')
def sleep(self):
"""睡"""
print(f"{self.name} 睡觉")
# 2. 定义猫类,猫类具有动物类的所有属性和方法,并且具有抓老鼠的特殊行为
class Cat(Animal):
"""猫类"""
def catch(self):
print(f"{self.name} 会抓老鼠...")
# 3. 定义狗类,狗类具有动物类的所有属性和方法,并且具有看门的特殊行为
class Dog(Animal):
"""狗类"""
def look_the_door(self):
"""看门"""
print(f"{self.name} 正在看家....")
# 4. 定义哮天犬类,哮天犬类具有狗类的所有属性和方法,并且具有飞的特殊行为
class XTQ(Dog):
"""哮天犬类"""
def fly(self):
"""飞"""
print(f"{self.name} 在天上飞...")
if __name__ == '__main__':
ani = Animal('佩奇', 2)
ani.eat()
ani.sleep()
cat = Cat('黑猫警长', 10)
cat.eat() # 调用 父类 animal 中的方法
cat.sleep() # 调用 父类 animal 中的方法
cat.catch() # 调用自己类的方法
dog = Dog('旺财', 3)
dog.eat()
dog.sleep()
dog.look_the_door()
xtq = XTQ('哮天犬', 100)
xtq.eat()
xtq.sleep()
xtq.look_the_door()
xtq.fly()
重写(override)
1, 什么是重写? 重写是在子类中定义了和父类中名字一样的方法.
2, 重写的原因? 为什么重写? 父类中的代码不能满足子类对象的需要
3, 重写的方式 1 覆盖式重写 2 扩展式重写
class Dog:
def bark(self):
print('汪汪汪叫......')
class XTQ(Dog):
# 需要哮天犬 嗷嗷嗷叫, 父类中的 bark 方法,不能满足子类对象的需要, 覆盖式重写
def bark(self):
print('嗷嗷嗷叫.....')
pass
if __name__ == '__main__':
xtq = XTQ()
xtq.bark()
class Dog:
def bark(self):
print('汪汪汪叫......')
print('汪汪汪叫......')
class XTQ(Dog):
# 需要哮天犬 嗷嗷嗷叫, 父类中的 bark 方法,不能满足子类对象的需要, 覆盖式重写
def bark(self):
# 调用父类中的功能
super().bark()
print('嗷嗷嗷叫.....')
print('嗷嗷嗷叫.....')
if __name__ == '__main__':
xtq = XTQ()
xtq.bark()
多态
多态:不同的子类对象调用相同的方法,产生不同的执行结果
class Dog:
def game(self):
print('普通狗简单的玩耍...')
class XTQ(Dog):
def game(self):
print('哮天犬在天上玩耍...')
class Person:
def play_with_dog(self, dog):
"""dog 是狗类或者其子类的对象"""
print('人和狗在玩耍...', end='')
dog.game()
if __name__ == '__main__':
dog1 = Dog()
xtq = XTQ()
xw = Person()
xw.play_with_dog(dog1)
xw.play_with_dog(xtq)
对象 属性 方法
类对象 就是 类, 就是使用 class 定义的类
在代码执行的时候, 解释期会自动的创建.
作用: 1, 使用类对象创建 实例对象 2, 存储一些类的特征值(类属性)
class Tool:
# 定义类属性 count,记录创建对象的个数
count = 0
def __init__(self, name):
self.name = name # 实例属性, 工具的名字
# 修改类属性的值
Tool.count += 1
if __name__ == '__main__':
# 查看 创建对象的个数
print(Tool.count) # 查看类属性
tool1 = Tool('锤子')
print(Tool.count)
tool2 = Tool('扳手')
print(Tool.count)
print(tool2.count) # 先找实例属性 count, 找不到, 找类属性 count, 找到,使用
类方法
class Tool:
# 定义类属性 count,记录创建对象的个数
count = 0
def __init__(self, name):
self.name = name # 实例属性, 工具的名字
# 修改类属性的值
Tool.count += 1
@classmethod
def show_tool_count(cls): # cls 就是类对象, 类名
return cls.count
if __name__ == '__main__':
# 查看 创建对象的个数
print(Tool.show_tool_count())
tool1 = Tool('锤子')
print(Tool.show_tool_count())
tool2 = Tool('扳手')
print(tool2.show_tool_count())
静态方法
方法中即不需要使用 实例属性, 也不需要使用 类属性, 可以 将这个方法定义为 静态方法
class 类名:
@staticmethod
def 方法名():
pass
文件
文件操作, 使用代码 来读写文件
1, Game 案例,最高分不能保存的, 可以将最高分保存到文件中,
2, 自动化, 测试数据在文件中保存的, 从文件中读取测试数据,进行自动化代码的执行
# # 1, 打开文件
# f = open('a.txt', 'w', encoding='utf-8')
# # 2, 写文件
# # f.write('hello python!')
# f.write('好好学习\n天天向上')
# # 3, 关闭文件
# f.close()
with open('a.txt', 'a', encoding='utf-8') as f:
f.write('good good study\n')
# with open('a.txt', encoding='utf-8') as f:
# buf = f.read()
# print(buf)
f = open('a.txt', encoding='utf-8')
data = f.read()
print(data)
f.close()
⽂件操作
按⾏读取⽂件 readline()
with open('a.txt', encoding='utf-8') as f:
buf = f.readline()
print(buf) # aaaaaa
buf1 = f.readline()
print(buf1) # bbbbbb
读取⼤⽂件
# with open('a.txt', encoding='utf-8') as f:
# while True:
# buf = f.readline() # 文件读完了,返回 空字符串
# if buf == "":
# break
# else:
# print(buf, end='')
with open('a.txt', encoding='utf-8') as f:
while True:
buf = f.readline() # 文件读完了,返回 空字符串
if buf: # 空字符串 是 False, 非空字符串 是 True
print(buf, end='')
else:
break
打开⽂件的⽅式
r w a 称为是⽂本⽅式打开, 适⽤于 ⽂本⽂件, 会对⼆进制进⾏编码转换
rb wb ab 称为是⼆进制⽅式打开, 可以打开⽂本⽂件和⼆进制⽂件, 但是 ⼆进制⽂件只能使⽤ ⼆进制⽅式打开,同时,不能传递 encoding 参数
with open('b.txt', 'rb') as f: buf = f.read() print(buf)
json ⽂件
1, json ⽂件的本质也是⽂本⽂件, 就可以直接使⽤ read 和 write 去进⾏操作
2, json ⽂件⽐较特殊, ⽐较像 Python 中的字典和列表
3, json ⽂件使⽤⽐较频繁,按照 read 和 write 的操作,⽐较
麻烦,专⻔的⽅法来操作 json ⽂件, 可以直接得到 Python 中的列表和字典
import json
with open('info.json', encoding='utf-8') as f:
buf = json.load(f)
print(type(buf))
print(buf)
# 姓名
print(buf.get('name'))
# 城市
print(buf.get('address').get('city'))
# 第二个爱好
print(buf.get('like')[1])
# 学校
print(buf.get('school'))
练习
import json
with open('info2.json', encoding='utf-8') as f:
data_list = json.load(f) # 列表
for data in data_list:
# sex = "男" if data.get('isMan') else "女"
if data.get('isMan'):
sex = "男"
else:
sex = '女'
print(f"姓名: {data.get('name')}, 年龄: {data.get('age')}"
f"性别: {sex}, 城市: {data.get('address').get('city')}")
# 条件为True 执行的代码 if 判断条件 else 条件为 False 执行的代码
# a = 'a ' if 3 > 1 else 'b'
json保存
import json
info = [{'name': '小明', 'age': 18}]
with open('info3.json', 'w', encoding='utf-8') as f:
# json.dump(info, f) #
# json.dump(info, f, ensure_ascii=False) # 直接显示中文
json.dump(info, f, ensure_ascii=False, indent=2) # 直接显示中文
import random
random.randint()
异常
try:
num = int(input('请输入一个整数数字:'))
num1 = 8 / num
print(num1)
except Exception as e:
print(f'发生了异常, {e}')
# # 1. 获取用户输入的数字
# num = input('请输入数字:')
# try:
# # 2. 判断获取的数字是否整数
# num = int(num) # 没有发生异常, 说明是整数,如果发生异常,说明不是整数
# except Exception as e:
# # 3. 如果不是整数, 提示输入错误
# print("输入错误", e)
# else:
# # 4. 如果是整数, 则进一步判断是奇数还是偶数
# if num % 2 == 0:
# print('偶数')
# else:
# print('奇数')
# # 5. 最终提示: 程序运行结束
# finally:
# print('程序运行结束')
# 1. 获取用户输入的数字
num = input('请输入数字:')
# 2. 判断获取的数字是否整数
if num.isdigit():
# 如果是 True, 表示是整数
# 类型转换
num = int(num)
# 4. 如果是整数, 则进一步判断是奇数还是偶数
if num % 2 == 0:
print('偶数')
else:
print('奇数')
# 3. 如果不是整数, 提示输入错误
else:
print('输入错误')
# 5. 最终提示: 程序运行结束
print('程序运行结束')
抛出异常
1, 在执⾏代码的过程中,之所以会发⽣异常,终⽌代码执⾏,是因为 代码执⾏ 遇到了 raise 关键字
2, raise 关键字的作⽤, 就是来抛出异常,让代码终⽌执⾏
3, 应⽤场景: ⾃⼰书写代码模块,让别⼈使⽤,为了让别⼈按照你的规定使⽤你的代码,你就可以在他不满⾜你条件的情况下,使⽤ raise 抛出异常
def input_password():
"""输入密码的函数"""
pwd = input('请输入密码:')
if len(pwd) < 8:
# raise 异常对象
raise Exception('密码长度不足 8 位')
else:
return pwd
异常传递
# 1. 定义函数 demo1() 提示用户输入一个整数并且返回
def demo1():
num = int(input('请输入一个整数'))
return num
# 2. 定义函数 demo2() 调用 demo1()
def demo2():
demo1()
# 3. 在主程序中调用 demo2()
if __name__ == '__main__':
try:
demo2()
except Exception as e:
print(e)