-
class
class后面紧接着是类名,类名命名规则大驼峰,紧接着是(object),表示该类是从哪个类继承下来的
定义类格式:
class 类名:
def 方法名(self, 参数):
pass
创建对象格式:
对象变量 = 类名()
- 初始化方法
使用类名()创建对象时,会自动调用init方法
init方法用来定义一个类具有哪些属性
class Person(object):
def __init__(self):
print("初始化方法")
self.name = "Naruto"
person = Person()
print(person.name)
class Cat(object):
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print('%s爱吃鱼' % self.name)
cat = Cat('Tom', 2)
print(cat.name)
cat.eat()
# 在类的外部给对象增加属性(不推荐)
cat.gender = "公"
- 内置方法del
对象从内存中被销毁前,会自动调用del - 内置方法str
必须返回一个字符串
如果在开发中,使用print输出一个对象时,希望打印自定义内容,可以使用str方法。
class Dog(object):
def __init__(self, name):
self.name = name
print('%s 来喽' % self.name)
def __del__(self):
print("%s 走了" % self.name)
def __str__(self):
return '我是小狗%s' % self.name
dog = Dog('xiaohei')
- 访问限制
在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。
class Students(object):
def __init__(self, name, score):
# 无法从外部访问实例变量.__name和实例变量.__score
self.__name = name
self.__score = score
def get_name(self):
return self.__name
def get_score(self):
return self.__score
def set_score(self, score):
if 0 <= score <= 100:
self.__score = score
else:
# raise ValueError('bad score')
self.__score = 0
student = Students('Naruto', 60)
print('%s: %s' % (student.get_name(), student.get_score()))
面向对象三大特性
封装: 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中;
继承: 实现代码的重用,相同的代码不需要重复的编写;
多态: 不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度;
-
封装
封装 是面向对象编程的一大特点;
面向对象编程的 第一步 —— 将 属性 和 方法 封装 到一个抽象的 类 中;
外界 使用 类 创建 对象,然后 让对象调用方法;
对象方法的细节 都被 封装 在 类的内部。
"""
需求:
1.士兵许三多有一把AK47
2.士兵可以开火
3.枪能够发射子弹
4.枪装填子弹 可增加子弹数量
"""
class Gun(object):
def __init__(self, model):
self.model = model
self.buttet_count = 0
def shoot(self):
if self.buttet_count > 0:
self.buttet_count -= 1
print("射击")
else:
print("%s没子弹" % self.model)
def add_bullet(self, count):
print("装子弹")
self.buttet_count += count
class Soldier(object):
def __init__(self, name):
self.name = name
self.gun = None
def add_gun(self, gun):
self.gun = gun
def add_bullet(self, count):
if self.gun is None:
print("没有枪")
else:
self.gun.add_bullet(count)
def fire(self):
if self.gun is None:
print("士兵没有枪")
else:
print("开火")
self.gun.shoot()
gun = Gun("AK47")
soldier = Soldier("许三多")
soldier.add_gun(gun)
soldier.add_bullet(20)
soldier.fire()
-
继承
1.子类对象不能在自己的方法内部,直接访问父类的 私有方法 或 私有属性;
2.子类对象可以通过父类的公有方法 间接 访问到 私有方法 和 私有属性。
- 单继承
class Animal(object):
def __init__(self, name):
self.name = name
def eat(self):
print("%s 吃" % self.name)
def drink(self):
print("%s 喝" % self.name)
def run(self):
print("%s 跑" % self.name)
def sleep(self):
print("%s 睡" % self.name)
class Dog(Animal):
def bark(self):
print("%s 叫" % self.name)
# 子类对象不能调用父类的私有方法
def __test(self):
print("Dog的私有方法")
# 子类对象可以通过调用父类的公有方法,间接调用父类的私有方法
def ttt(self):
print("Dog的公有方法")
self.__test()
class Cat(Animal):
def catch(self):
print("%s 抓老鼠" % self.name)
class RoaringDog(Dog):
def fly(self):
print("%s 会飞" % self.name)
# 重写(override)父类方法
def bark(self):
# super().bark() # 同时执行父类中的方法
print("%s叫的和神一样" % self.name)
dog = Dog("旺财")
dog.eat()
dog.bark()
dog.ttt()
cat = Cat("汤姆")
cat.drink()
cat.catch()
xtq = RoaringDog('哮天犬')
xtq.run()
xtq.fly()
xtq.bark()
- 多继承
子类可以拥有多个父类,并且具有所有父类的属性和方法
注意:如果父类之间存在同名的属性或方法,应该避免使用多继承
class A(object):
def test(self):
print("A的test()方法")
class B(object):
def demo(self):
print("B的demo()方法")
class C(A, B):
pass
c = C()
c.test()
c.demo()
-
多态
不同的子类对象调用相同的父类方法,产生不同的执行结果。
1.多态可以增加代码的灵活度
2.以继承 和 重写父类方法 为前提
3.是调用方法的技巧,不会影响到类内部设计
class Dog(object):
def __init__(self, name):
self.name = name
def game(self):
print("%s蹦蹦跳跳的玩耍~" % self.name)
class XiaoTianQuan(Dog):
def game(self):
print("%s飞到天上去玩耍" % self.name)
class Person(object):
def __init__(self, name):
self.name = name
def game_with_dog(self, dog):
print("%s 和 %s 快乐的玩耍" % (self.name, dog.name))
dog.game()
wangcai = Dog('旺财')
xiaolan = Person('小兰')
xiaolan.game_with_dog(wangcai)
xiaotianquan = XiaoTianQuan('哮天犬')
xiaohong = Person('小红')
xiaolan.game_with_dog(xiaotianquan)
- 类属性 类方法 静态方法
- 类属性
实例属性属于各个实例所有,互不干扰;
类属性属于类所有,所有实例共享一个属性;
不要对实例属性和类属性使用相同的名字,否则将产生难以发现的错误.
访问类属性方法:
1.类名.类属性
2.对象.类属性(不推荐)
注意:如果使用 对象.类属性 = 值 赋值语句,只会给对象添加一个属性,而不会影响到类属性的值
- 类方法
类方法就是针对类对象定义的方法;
在类方法内部可以直接访问类对象或其它类方法;
类方法需要用@classmethod修饰器来标识,告诉解释器 这是一个类方法;
语法:
@classmethod
def 类方法名(cls)
pass
注:类方法的第一个参数是cls,类似实例方法的self,在方法内部可以通过cls访问类属性,也可以通过cls调用其它类方法.
class Tool(object):
count = 0
@classmethod
def show_tool_count(cls):
print('有%d个工具' % cls.count)
def __init__(self, name):
self.name = name
Tool.count += 1
tool1 = Tool('斧头')
print('有%d个工具' % Tool.count)
tool2 = Tool('锤子')
print('有%d个工具' % Tool.count)
Tool.show_tool_count()
- 静态方法
使用场景:在开发时,如果需要在类中封装一个方法,这个方法:
不需要 访问实例属性 或 调用实例方法,也不需要 访问类属性 或 调用类方法,
可以将这个方法封装为静态方法
语法:
@staticmethod
def 静态方法名():
pass
调用方法: 类名.静态方法()
class Dog(object):
dog_count = 0
@staticmethod
def run():
print("🏃")
Dog.run()
实例方法:方法内部需要访问实例属性,实例方法内部可以使用 类名. 访问类属性
类方法:方法内部只需要访问类属性
静态方法:方法内部不需要访问 实例属性 和 类属性
-
单例Singleton
目的 —— 让 类 创建的对象,在系统中 只有 唯一的一个实例
每一次执行 类名() 返回的对象,内存地址是相同的
使用类名创建对象时,会先调用new 方法为对象分配内存空间
new是一个由object基类提供的内置的静态方法,主要作用有两个:
1.在内存中为对象分配内存空间
2.返回对象的引用
python解释器获得对象的引用后,将引用作为第一个参数传递给init方法
注:new 是静态方法,需主动传递cls参数
class MusicPlayer(object):
instance = None
init_flag = False
def __new__(cls, *args, **kwargs):
if cls.instance is None:
cls.instance = super().__new__(cls)
print("创建对象,分配内存空间")
return cls.instance
def __init__(self):
# 初始化只执行一次
if MusicPlayer.init_flag:
return
MusicPlayer.init_flag = True
print("播放器初始化")
player = MusicPlayer()
print(player)
player2 = MusicPlayer()
print(player2)
-
异常Exception
在程序开发中,如果 对某些代码的执行不能确定是否正确,可以增加 try(尝试) 来 捕获异常
捕获异常最简单的语法格式:
try:
尝试执行的代码
except:
出现错误的处理
- 根据错误类型捕获异常
try:
num = int(input("请输入一个整数:"))
result = 8 / num
except ValueError as e:
print('except:', e)
except ZeroDivisionError as e:
print('except:', e)
except Exception as e:
print("未知错误 %s" % e)
else:
# 没有异常才会执行的代码
print(result)
finally:
# 无论是否有异常 都会执行的代码
print("-" * 50)
- 异常的传递
当方法的执行出现异常,会将异常传递给调用方法的一方;
如果传递到主程序,仍然没有异常处理,程序才会被终止;
提示:
在开发中,可以在主函数中增加异常捕获,在主函数中调用的其它函数,只要出现异常,就会传递到主函数的异常捕获中;
这样就不需要在代码中增加大量的异常捕获,能够保证代码的整洁;
def demo1():
return int(input("请输入一个整数:"))
def demo2():
return demo1()
try:
demo2()
except ValueError:
print("请输入正确整数")
except Exception as e:
print('未知错误 %s' % e)
- 抛出raise异常
在开发中,除了代码执行出错会抛出异常之外,还可以根据应用程序特有的业务需求主动抛出异常
步骤:
1.创建一个Exception 异常类
2.使用raise关键字抛出异常对象
def input_password():
password = input("请输入密码:")
if len(password) >= 8:
return password
raise Exception("密码长度不够")
try:
print(input_password())
except Exception as e:
print(e)
- 模块和包
- 模块
每一个以扩展名 py 结尾的 Python 源代码文件都是一个 模块;
模块名 同样也是一个 标识符,需要符合标识符的命名规则;
在模块中定义的 全局变量 、函数、类 都是提供给外界直接使用的 工具;
模块 就好比是 工具包,要想使用这个工具包中的工具,就需要先 导入 这个模块;
模块的导入:
import 模块1
import 模块2
通过 模块名. 使用模块提供的全局变量、方法、类
模块导入时指定别名: import 模块1 as 模块别名
局部导入from...import:
如果希望从一个模块中导入部分工具,可以使用from...import 的方式
import 模块名是一次性将模块中所有工具全部导入,并且通过模块名/别名访问
from 模块名1 import 工具名
导入之后可以直接使用模块提供的工具--全局变量、函数、类
注:如果两个模块,存在同名的函数,后导入模块的函数会覆盖先导入模块的函数
从模块中导入所有工具(知道)
from...import *
在导入模块文件时,文件中所有没有缩进的代码都会被执行一遍
name 属性可以做到,测试模块的代码只在测试情况下被运行,而在被导入时不会执行
name是python的内置属性,记录着一个字符串
如果是被其它文件导入的,name就是文件名
py_17_test_module.py
def say_hello():
print("hello!!!")
def say_hi():
print("hi???")
# 被其它文件导入时,不会被执行
if __name__ == "__main__":
print("小米开发的模块")
import py_17_test_module
import py_17_test_module as tm
from py_17_test_module import say_hello
py_17_test_module.say_hello()
tm.say_hi()
say_hello()
# 模块路径
print(py_17_test_module.__file__)
print(py_17_test_module.__name__) # py_17_testModule
print(__name__) # __main__
- 包
包是一个包含了多个模块的特殊目录
目录下有一个特殊文件 init.py
包名的命名方式与变量名一致,小写字母+_
使用 import 包名 可以一次性导入包中的所有模块
_init.py
要在外界使用包中的模块,需要在_init.py中指定对外界提供的模块列表
# __init__.py内容
from . import py_17_send_message
from . import py_17_receive_message
import py_17_message
py_17_message.py_17_send_message.send("你是🐷吗")
txt = py_17_message.py_17_receive_message.receive()
- 发布模块(知道)
步骤:
1)创建setup.py文件
from distutils.core import setup
setup(name="xh_message", # 包名
version="1.0.0", # 版本号
description="发送和接收消息模块", # 描述信息
long_description="完整的发送和接收消息模块", # 完整的描述信息
author="xiaohan", # 作者
author_email="xiaohan@gamil.com", # 作者邮箱
url="www.xiaohan.com", # 主页
py_17_message=["py_17_message.py_17_send_message", "py_17_message.py_17_receive_message"]) # 模块中包含的文件名称
2)构建模块
终端:$ python3 setup.py build
3)生成发布压缩包
终端:$ python3 setup.py sdist
安装模块
$ tar -zxvf py_17_message-1.0.0.tar.gz
$ sudo python3 setup.py install
卸载模块
直接从安装目录将模块目录删除即可
$ cd /usr/local/lib/python3/dist-packages/
$ sudo rm -r py_17_message*
可以通过file内置属性获取模块所在路径
$ ipython3
$ import py_17_message
$ py_17_message.file
- 文件
- 文件的基本操作
函数/方法 | 说明 |
---|---|
open | 打开文件 并且返回文件操作对象 |
read | 将文件内容读取到内存 |
write | 将指定内容写入文件 |
close | 关闭文件 |
注:
open: 函数默认以只读方式打开文件
如果文件存在,返回文件操作对象
如果文件不存在,会抛出异常
read: 方法可以一次性读入并返回文件的所有内容
close: 方法负责关闭文件
try:
file = open("text") # 打开文件(默认只读方式)
text = file.read() # 读取文件
text2 = file.read() # 已经读取过来,文件指针在末尾,读取不到任何内容
file.close() # 关闭文件
print(text)
print(len(text2))
except FileNotFoundError:
print("文件不存在")
except Exception as e:
print("未知错误 %s" % e)
open方法参数:
1.第一个参数是要打开的文件名
2.第二个参数是访问方式
参数 | 说明 |
---|---|
r | 以只读方式打开。文件指针会放在文件开头,如果文件不存在会抛出异常 |
w | 以只写方式打开。如果文件存在会被覆盖,如果文件不存在,创建新文件 |
a | 以追加方式打开。如果文件已存在,文件指针会方法在文件结尾;如果文件不存在,会创建文件 |
r+ | 以读写方式打开。文件指针会放在文件开头,如果文件不存在会抛出异常 |
w+ | 以读写方式打开。如果文件存在会被覆盖,如果文件不存在,创建新文件 |
a+ | 以读写方式打开。如果文件已存在,文件指针会方法在文件结尾;如果文件不存在,会创建文件 |
file = open("text", "a")
file.write("hello")
file.close()
file = open("text")
print(file.read())
file.close()
- 按行读取文件内容
readline 方法可以一次读取一行内容
方法执行后,会把文件指针移动到下一行,准备再次读取
# 读取大文件
file = open("text")
while True:
text = file.readline()
if not text:
break
print(text, end="")
file.close()
- 文件指针(知道)
文件指针 标记从哪个位置开始读取数据
第一次打开文件时,通常文件指针会指向文件的开始位置
当执行了read方法后,文件指针会移动到文件内容的末尾 - 复制文件
# 小文件复制
file_read = open("text")
file_write = open("text[副本]", "w")
text = file_read.read()
file_write.write(text)
file_read.close()
file_write.close()
file = open("text[副本]")
print(file.read())
# 大文件复制
file_read = open("text")
file_write = open("text[副本]", "w")
while True:
text = file_read.readline()
if not text:
break
file_write.write(text)
file_read.close()
file_write.close()
file = open("text[副本]")
print(file.read())
- 文件\目录的常用管理操作
需要导入os模块
文件操作:
方法名 | 说明 | 示例 |
---|---|---|
rename | 重命名文件 | os.rename(源文件名, 目标文件名) |
remove | 删除文件 | os.remove(文件名) |
path.isfile | 判断是否是文件 | os.path.isfile(路径) |
目录操作:
方法名 | 说明 | 示例 |
---|---|---|
listdir | 目录列表 | os.listdir(目录名) |
mkdir | 创建目录 | os.mkdir(目录名) |
rmdir | 删除目录 | os.rmdir(目录名) |
getcwd | 获取当前目录 | os.getcwd() |
chdir | 修改工作目录 | os.chdir(目标目录) |
path.isdir | 判断是否是目录 | os.path.isdir(路径) |
print(os.getcwd())
# os.mkdir("测试")
os.remove(os.getcwd() + "/text[副本]")
-
eval
eval函数 可以将字符串当成有效的表达式来求值,并返回计算结果
注:开发时,不要使用eval直接转换input的结果
# 基本数学计算
eval("1 + 1") # 2
# 字符串重复
eval("'+' * 10") # ++++++++++
# 字符串转列表
type(eval("[1,2,3,4]")) # <class 'list'>
# 字符串转字典
type(eval("{'name':'xiaolan', 'age':'16'}")) # <class 'dict'>
str = input("请输入算数题:")
print(eval(str))
"""
__import__('os').system('ls')
# 等价代码
import os
os.system("终端命令")
执行成功,返回0
执行失败,返回错误信息
"""
eval("__import__('os').system('ls')")
网友评论