64. 方法的值的传递及调用类内部的属性、方法
文章目录
- 64. 方法的值的传递及调用类内部的属性、方法
- 1. 知识回顾
- 2. 值的传递
- 3. 没有值
- 4. 需要向方法传递值
- 5. 调用类内部的属性和方法
- 6. 综合代码
- 7. 类在爬虫中的应用
- 7.1 创建类
- 7.2 创建对象
- 7.3 调用方法
- 7.4 第2次调用方法
- 7.5 第2次调用方法
- 8. 总结
1. 知识回顾
定义在类外的函数称为自定义函数。
定义在类里的函数称为方法。
直接写在类里的变量称为类属性。
创建对象语法:
对象名=类名( )
调用属性语法:
对象名.属性
调用方法语法:
对象名.方法名(值,…)
【语法总结】
都是对象名开头。
创建对象要用等于号=
。
属性和方法是类自己的东西,用个英文小圆点.
就能实现。
因为方法要传值进去,因此需要紧跟一个英文圆括号()
。
2. 值的传递
调用方法语法:
对象名.方法名(值,…)
这里的值是指外界要传入到方法中的值。
方法的值传递有2种情况:
-
没有值
-
有值
3. 没有值
对象名.方法名()
不需要向方法传递值时括号为空。
观察下面代码的最后一行,重点关注括号。
# 定义一个车类,类名为Cars
class Cars:
# 在类中定义的函数称为方法
def drive(self):
# 方法中的代码块
print('汽车正在向前行驶!')
# 创建对象:对象名=类名( ),这里对象名为aodi_A6
aodi_A6 = Cars( )
# 调用方法检查汽车前进的功能:对象名.方法名(值)
aodi_A6.drive()
【终端输出】
汽车正在向前行驶!
print('汽车正在向前行驶!')
上述print
输出语句是drive
方法的代码块。
这个代码块是一个输出语句。
输出语句是固定的,语句中没有任何需要传值的变量,因此调用方法时即能输出该语句,不需要外界传递任何参数。
因此调用方法时括号为空。
不需要传递参数时括号为空。
aodi_A6.drive()
这里不需要传入值,因此括号为空。
4. 需要向方法传递值
对象名.方法名(值,…)
需要传递值时括号中写入具体值或变量名。
我们生产的汽车除了要检查它的前进、刹车、倒车功能。
我们还可以测试它的时速。
【体验代码】
# 定义一个车类,类名为Cars
class Cars:
# 在类中定义的函数称为方法,speed是外界传入的值
def drive(self, speed):
print(f'汽车可以提速到{speed}公里每小时!')
# 创建对象:对象名=类名( )
aodi_A6 = Cars( )
# 调用方法语法:对象名.方法名(值),120是要传入方法的具体值
aodi_A6.drive(120)
【终端输出】
汽车可以提速到120公里每小时!
speed [spiːd]速度。
def drive(self, speed):
pass
-
方法中的第1个参数必须是
self
。 -
方法的第2个参数是
speed
。speed
是调用方法时要传入的值。
print(f'汽车可以提速到{speed}公里每小时!')
上述print
输出语句是drive
方法的代码块。
这个代码块是一个输出语句。
但这个输出语句不是固定的。
输出语句中多加了一个变量speed
。
输出语句随外界的传入的值的改变而改变。
这里的f
的作用是格式化字符串。
120
是调用方法时给类中的方法传入的值。
120
先传值给方法中的speed
。
方法中的speed
将接收的值120
传递给输出语句的speed
。
因此才输出汽车可以提速到120公里每小时!
传递的值改变,输出的内容也会跟着改变。
【值的传递过程】
-
调用类的方法时,我们直接忽略第一个
self
参数。 -
特别注意其它参数值按位置传递入类的方法。
特别注意方法的参数是按位置进行传递的。
【举例说明】
def drive(self, speed, type, price):
pass
aodi_A6.drive(120, "奥迪", "40万")
参数值按位置传递给类的方法。
-
忽略
self
参数。 -
120
传递给speed
。 -
"奥迪"
传递给type
。 -
"40万"
传递给price
。
【f格式化字符串编写思路】
步骤一:编写格式化模板
-
我们要输出的内容是:
汽车可以提速到120公里每小时!
-
把要格式化的内容用英文大括号加变量名
{speed}
替换:
汽车可以提速到{speed}公里每小时!
步骤二:添加格式化符号f
在格式化模板前添加一个表示需要格式化字符串的符号即小写的英文字母f
即可。
print(f'汽车可以提速到{speed}公里每小时!')
5. 调用类内部的属性和方法
# 定义一个车类,类名为Cars
class Cars:
# 直接写在类里的变量称为类属性
color_1 = "红色"
type_1 = "小轿车"
# 定义在类中的函数称为方法
def drive(self, speed):
print(f'经测试,{self.type_1}的最高时速是{speed}公里每小时。')
print('经测试,{}的最高时速是{}公里每小时。'.format(self.type_1, speed))
# 创建对象,对象名为aodi_A6
aodi_A6 = Cars( )
# 查看汽车的车型
print(aodi_A6.type_1)
# 调用方法
aodi_A6.drive(120)
【终端输出】
小轿车
经测试,小轿车的最高时速是120公里每小时。
经测试,小轿车的最高时速是120公里每小时。
# 调用属性
print(aodi_A6.type_1)
# 调用方法
aodi_A6.drive(120)
上述两段代码,一个调用属性,一个是调用方法。
观察代码我们发现,调用方法时是可以不用print
输出语句的。。
观察上述代码的终端,我们输出了2个语句。
是因为我在drive方法中写了2个print语句,目的是复习下format字符串格式化方法。
【format格式化字符串编写思路】
步骤一:编写格式化模板
-
我们要输出的内容是:
经测试,小轿车的最高时速是120公里每小时。
-
把要格式化的内容用英文大括号
{}
替换:
小轿车
替换为{}
120
替换为{}
'经测试,{}的最高时速是{}公里每小时。
步骤二:语法关键字
-
输入一个英文小圆点
.
-
format
关键字
步骤三:添加要格式化的变量名。
self.type_1
要格式化的第1个字符串type_1
。
speed
要格式化的第2个字符串speed
。
观察代码,大家发现type_1
变量前多了一个self.
。
这是为什么呢?
我们调用方法外的属性的语法为:对象名.属性
我们在类内部的方法中调用类的属性或其它类的方法时,需要在前面加上slef. 如:
self.属性名
self.方法名
print(aodi_A6.type_1)
这句代码是在方法外调用类的属性,因此对象名.属性。
print('经测试,{}的最高时速是{}公里每小时。'.format(self.type_1, speed))
这里是在类中的drive
方法中调用类的属性,因此用self.属性名。
这个其实不难,大家注意区分是在方法中调用还是在方法外调用即可。
调用方法也是同样的语法。
如果在类外调用方法用:
对象名.方法名(值,…)
如果类中的方法调用其他方法:
slef.方法名(值,…)
假设一个类有5个方法,方法3要调用方法2,则在方法名前加slef.
6. 综合代码
# 定义一个车类,类名为Cars
class Cars:
# 直接写在类里的变量称为类属性
color_1 = "红色"
color_2 = "黑色"
color_3 = "黄色"
color_4 = "绿色"
type_1 = "小轿车"
type_2 = "越野车"
type_3 = "公交车"
type_4 = "跑车"
# 在类中定义的函数称为方法
# 方法的第1个参数必须是slef
def drive(self, speed):
# 方法中的代码块
print(f"经测试,{self.color_4}的{self.type_4}的最高时速是{speed}公里每小时。")
print("经测试,{}的{}的最高时速是{}公里每小时。".format(self.color_2, self.type_4, speed))
print("经测试,{}的{}的最高时速是{}公里每小时。".format(self.color_1, self.type_4, speed))
# 创建对象:对象名.类名( )
paoche = Cars( )
# 查看汽车的颜色
print(paoche.color_4)
print(paoche.color_2)
print(paoche.color_1)
# 查看汽车的车型
print(paoche.type_4)
# 调用对象:对象名.方法名(值)
# 测试车速
paoche.drive(230)
【终端输出】
绿色
黑色
红色
跑车
经测试,绿色的跑车的最高时速是230公里每小时。
经测试,黑色的跑车的最高时速是230公里每小时。
经测试,红色的跑车的最高时速是230公里每小时。
这里我创建了的对象是跑车。
并且生产了不同颜色的跑车。
大家可以编写代码生产一款你喜欢的跑车,可以试着给跑车多增加几个属性,多传入结果值。例如价格、车长等等。
7. 类在爬虫中的应用
类的知识点相对抽象,初学者很难理解,下面我们通过一个实例来更深层次的理解类的作用。
下面是爬取某站视频的部分代码,大家重点关注类相关的知识点即可。
【备注】下面的代码不全,运行下面的代码是不会成功下载到视频的。
'''批量下载视频'''
import requests # 网络请求模块
import time # 时间模块
import random # 随机模块
import os # 操作系统模块
import re # 正则表达式
# 哔哩哔哩小视频json地址
json_url = 'http://api.vc.bilibili.com/board/v1/ranking/top?page_size=10&next_offset={page}1&tag=%E4%BB%8A%E6%97%A5%E7%83%AD%E9%97%A8&platform=pc'
class Crawl():
def __init__(self):
# 创建头部信息
self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0'}
def get_json(self,json_url):
response = requests.get(json_url, headers=self.headers)
# 判断请求是否成功
if response.status_code == 200:
return response.json() # 返回json信息
else:
print('获取json信息的请求没有成功!')
#下载视频
def download_video(self,video_url,titlename):
# 下载视频的网络请求
response = requests.get(video_url, headers=self.headers, stream=True)
if not os.path.exists('video'): # 如果video目录不存在时
os.mkdir('video') # 创建该目录
if response.status_code == 200: # 判断请求是否成功
if os.path.exists('video'):
with open('video/'+titlename+'.mp4', 'wb')as f: # 将视频写入指定位置
for data in response.iter_content(chunk_size=1024): # 循环写入,实现一段一段的写
f.write(data) # 写入视频文件
f.flush() # 刷新缓存
print('下载完成!')
else:
print('视频下载失败!')
if __name__ == '__main__':
c = Crawl() # 创建爬虫类对象
for page in range(0,10): # 循环请求10页每页10组数据
json = c.get_json(json_url.format(page=page)) # 获取返回的json数据
infos = json['data']['items'] # 信息集
for info in infos: # 遍历信息
title = info['item']['description'] # 视频标题
# 只保留标题中英文、数字与汉字,其它符号会影响写入文件
comp = re.compile('[^A-Z^a-z^0-9^\u4e00-\u9fa5]')
title = comp.sub('', title) # 将不符合条件的符号替换为空
video_url = info['item']['video_playurl'] # 视频地址
print(title,video_url) # 打印提取的视频标题与视频地址
c.download_video(video_url, title) # 下载视频,视频标题作为视频的名字
time.sleep(random.randint(3, 6)) # 随机产生获取json请求的间隔时间
7.1 创建类
class Crawl():
pass
crawl[krɔːl]:爬虫
-
创建类的代码在程序的第12行。
-
类名为
Crawl
,类名的首字母C
是大写。 -
class
是定义类的关键字。
7.2 创建对象
c = Crawl()
-
创建对象的代码在程序的第41行,语法为:对象名=类名( )
-
类名为
Crawl
-
给对象起的名字为
c
7.3 调用方法
def get_json(self,json_url):
response = requests.get(json_url, headers=self.headers)
# 判断请求是否成功
if response.status_code == 200:
return response.json() # 返回json信息
else:
print('获取json信息的请求没有成功!')
在类中定义的函数称为方法。
上面这段代码是类中的一个方法,该方法的作用是访问网页。
-
方法名为
get_json
-
方法的第1个参数必须是slef,第2个参数是json_url。
-
剩下的语句是代码块。
代码块的大概意思是:
requests.get
利用是请求模块中的get
方法访问网页。
if response.status_code == 200:
如果返回的状态码是200,访问网页成功。
return response.json()
返回json信息。
如果返回的状态码不是200,访问网页失败,输出获取json信息的请求没有成功!
该方法的调用代码在程序的第43行,如下:
json = c.get_json(json_url.format(page=page))
-
这是在类外部调用方法,语法为:对象名.方法名(值)
-
对象名为
c
-
方法名
get_json
-
这里要传入的值有点复杂,它是字符串格式化语句。
# 哔哩哔哩小视频json地址
json_url = 'http://api.vc.bilibili.com/board/v1/ranking/top?page_size=10&next_offset={page}1&tag=%E4%BB%8A%E6%97%A5%E7%83%AD%E9%97%A8&platform=pc'
json_url在程序的第10行就进行了赋值。
但注意这个变量里有一个{page}
需要格式化的字符。
7.4 第2次调用方法
类的第二个方法如下:
def download_video(self,video_url,titlename):
# 下载视频的网络请求
response = requests.get(video_url, headers=self.headers, stream=True)
if not os.path.exists('video'): # 如果video目录不存在时
os.mkdir('video') # 创建该目录
if response.status_code == 200: # 判断请求是否成功
if os.path.exists('video'):
with open('video/'+titlename+'.mp4', 'wb')as f: # 将视频写入指定位置
for data in response.iter_content(chunk_size=1024): # 循环写入,实现一段一段的写
f.write(data) # 写入视频文件
f.flush() # 刷新缓存
print('下载完成!')
else:
print('视频下载失败!')
该方法的作用是下载视频。
def download_video(self,video_url,titlename):
pass
-
方法名
download_video
-
方法的第1个参数:
self
-
方法的第2个参数:
video_url
-
方法的第3个参数:
titlename
7.5 第2次调用方法
c.download_video(video_url, title)
-
c是对象名
-
download_video
方法名 -
video_url, title
要传入方法的值。
【温馨提示】
为了讲解类的相关知识,例子中的代码块仅有1个输出语句,许多同学会好奇一个输出语句不用类反而更方便,为什么多加一层。
因此多写了累在爬虫中的应用这部分笔记。
大家不需要知道每句代码的意思,重点关注一下类相关的语法,并对爬虫的结构有个框架的认识。
大家继续加油哦,再坚持一下下,我们就快能自己写爬虫代码批量下载视频了。