爬虫基础

首先,我们要搞懂一个东西。那就是网页,当我们登录一个网址时,可以看到一个光鲜亮丽的网页,构成它的就是一些代码,这种代码称之为HTML,是一种浏览器看得懂的语言。通过浏览器将这种语言转化成我们能够看到的网页。
同时除了HTML以外还可以使用CSS跟JavaScript。
其次,关于简单的爬虫所需要用到的库有:urllib.request中的urlopen,BeautifulSoup,request,re。
首先urlopen可以实现对于url的访问,并且读取其中的信息。
BeautifulSoup用以选取信息;用以代替正则表达式。

from bs4 import BeautifulSoup
from urllib.request import urlopen

# if has Chinese, apply decode()
html = urlopen("https://baidu.com").read().decode('utf-8')

soup = BeautifulSoup(html, features='lxml')
print(soup.input)

如果说HTML是框架的话,那么CSS可以理解成衣服。如果只有框架没有衣服,那么整个网页会看起来十分的死板,所以需要通过添加衣服来使得整个网页更加的绚丽多彩。
Class作为CSS的一个重要组成部分,可以简单想象成python中的class。对于每一个class都会有自己的属性如颜色大小字体等,使得每个class都不一样,让整个网页看起来更加悦目一些。因此我们可以通过查找class的具体名称来查找一类组件。

from bs4 import BeautifulSoup
from urllib.request import urlopen

# if has Chinese, apply decode()
html = urlopen("https://baidu.com").read().decode('utf-8')

soup = BeautifulSoup(html, features='lxml')

# use class to narrow search
a = soup.find_all('div', {"class": "s_tab"})
for m in a:
    print(m.get_text())

正则表达式,通过不同的正则化可以使得查找的条件更加的多样化。这里就不展开讲了。
如果只是简单的读取数据,收集信息,使用BeautifulSoup就已经差不多了,然而随着其他需求的增多,我们可能会需要下载、上传图片、发送信息等功能,这时候Request就可以用来处理这些问题。其中用于加载网页的有几种方式,其中最常见的就是get跟post两种。最大的区别就在于post可以对网站进行操作,而get除了看跟收集信息,其他的都做不了。

data = {'firstname': '莫烦', 'lastname': '周'}
r = requests.post('http://pythonscraping.com/files/processing.php', data=data)
print(r.text)

Cookies在浏览器中十分的重要,就像是缓存,记录着你的一些私人信息,如账号密码等,方便你的使用。然后在我们正常爬取数据的时候需要一次又一次的登录,每一次都需要传递cookies,过于麻烦,所以可以通过使用request中的Session来保存每一次的cookies,方便了之后的操作。

session = requests.Session()
payload = {'username': 'Morvan', 'password': 'password'}
r = session.post('http://pythonscraping.com/pages/cookies/welcome.php', data=payload)
print(r.cookies.get_dict())

# {'username': 'Morvan', 'loggedin': '1'}


r = session.get("http://pythonscraping.com/pages/cookies/profile.php")
print(r.text)

下载文件
第一种:在urllib中有一个下载功能urlretrieve,只需要输入下载地址跟存放的位置,就可以自动下载过来。
第二种:使用requests通过新建一个文件,然后将网页的文件写入其中。
第三种:也是使用requests,当我们下载较大的文件时,用第二种方法它会缓存直到整个文件都下载好了再存入硬盘里不是很方便。所以使用chunck从而实现了实时下载文件

#一 from urllib.request 
    import urlretrieve 
    urlretrieve(IMAGE_URL, './img/image1.png') 
#二 import requests 
    r = requests.get(IMAGE_URL) 
    with open('./img/image2.png', 'wb') as f: 
        f.write(r.content) 
#三 r = requests.get(IMAGE_URL, stream=True) 
    with open('./img/image3.png', 'wb') as f: 
       for chunk in r.iter_content(chunk_size=32): 
           f.write(chunk)

多进程分布式爬虫
当我们正常使用爬虫的时候,它是一个线性的过程,只有等到这一个爬完了,才会到另一个地方爬另外的东西。这样子,再等待的过程中,浪费了好多的时间。因此使用多进程分布式爬虫可以有效地减缓时间的浪费,最大化的利用电脑。

异步线程爬虫
其主要原理都相差不多,都是通过抽出在执行过程中浪费的时间来提高爬虫效率。

高级爬虫scrapy 相当于专门用于爬虫的库
对于scrapy还有大量的知识没有掌握,这里不做太多的介绍,如果之后还有继续学习爬虫的话,会去认真看看scrapy的!!!

参考链接:https://mofanpy.com/tutorials/data-manipulation/scraping/

python小项目-图片转化视频

用到了cv2、os、PIL 三个库

在弄视频转化字符动画时自己弄出来的代码。

import cv2
import os
from  PIL import  Image

fps = 3
img_root = 'E://python_text//'

data = os.listdir(img_root) #保存当前目录文件列表

image = Image.open(img_root+'pi0.png')

fourcc = cv2.VideoWriter_fourcc('m','p','4','v')
videoWriter = cv2.VideoWriter('tett1.mp4',fourcc,fps,image.size)

num = 0
for i in data:
    ##print(i)
    print(i)
    if i == 22:
        break
    if i.endswith('.png'):
        frame = cv2.imread(img_root+'pi'+str(num)+'.png')
        num += 1
        videoWriter.write(frame)
videoWriter.release()
cv2.destroyAllWindows()

 

 

python小项目-视频转化成字符动画(高级)

结合了之前所实现的视频转化字符动画,由于其在Pycharm上面显示不能够连贯逐帧显示,只能放在shell里面去运行,过于麻烦,所以对其进行了相应的改进。再加上之前所学习的将字符串转化成图片的经验,这次直接将视频转化成字符视频。

原理

  1. 通过之前的步骤将每一帧的图像以字符串的形式保存在列表当中;
  2. 将每一帧的字符串保存为图片
  3. 同时将读取之前保存的图片逐步转化成视频即可
import cv2
import os
from PIL import  Image,ImageDraw,ImageFont

show_heigth = 50
show_width = 150

ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")

char_len = len(ascii_char)

def get_char(r,g,b,alpha = 256):
    if alpha == 0:
        return ' '
    length = len(ascii_char)
    gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
    #由于灰度大于字符 所以需要将灰度分配在不同的字符上
    unit = (256.0 + 1)/length
    return ascii_char[int(gray/unit)]

vc = cv2.VideoCapture("pi.mp4")  # 加载一个视频

if vc.isOpened():  # 判断是否正常打开
    rval, frame = vc.read()
else:
    rval = False

frame_count = 0
outputList = []  # 初始化输出列表
num = 0
while rval:  # 循环读取视频帧
    if frame_count % 5 ==0:

        cv2.imwrite('%s.jpg'%('pic_'+str(num)),frame)
        name = 'pic_' + str(num)+'.jpg'

        im = Image.open(name)
        im = im.resize((show_width, show_heigth), Image.NEAREST)
        num += 1

        text = ""

        for i in range(show_heigth):
            for j in range(show_width):
                text += get_char(*im.getpixel((j,i)))#*可以传递元组
            text += '\n'
        outputList.append(text)
        os.remove(name)

    frame_count = frame_count + 1
    rval, frame = vc.read()
print("处理完毕")

num = 0

fourcc = cv2.VideoWriter_fourcc('m','p','4','v')
fps = 3
videoWriter = cv2.VideoWriter('tett2.mp4',fourcc,fps,(show_width*8,show_heigth*16))
for frame in outputList:
    
    font = ImageFont.load_default()
    im_txt = Image.new('L', (show_width * 8, show_heigth * 16), 255)
    d = ImageDraw.Draw(im_txt)
    d.text((0, 0), frame, font=font)

    im_txt.save('pi%s.jpg'%(num))

    name = 'E://python_text//'+'pi'+str(num)+'.jpg'
    i = cv2.imread(name)
    #i.show()
    videoWriter.write(i)
    os.remove(name)
    num += 1

videoWriter.release()
cv2.destroyAllWindows()

心得:
对于如何将图片合成视频有了一定的了解以及os一些删除、显示等功能

fourcc = cv2.VideoWriter_fourcc('m','p','4','v') #视频编码格式
videoWriter = cv2.VideoWriter('tett2.mp4',fourcc,fps,(show_width*8,show_heigth*16))
i = cv2.imread(name)
videoWriter.write(i)  #将图片写了视频中

 

python小项目-视频转化成字符动画(初级)

这次的所有代码都是基于之前所作的小项目图片转化成字符图,这次进行功能上面的提升,能够转化视频输出为字符动画。
想到视频第一反应肯定是opencv,这里所使用的程序库有Pillow、argparse、cv2、os

思路:同样的首先定义好命令行的参数,获取输入视频的路径、长宽;
之后定义好能够将图片RGB值转化成之前设定好的字符串列表的函数;
通过cv2来截取每一帧的视频并保存为图片格式;
逐个保存并逐个读取;
通过getchar函数去获得每一个字符图,并用字符列表来保存。
最后由于IDLE输出起来不是特别的顺畅,所以在shell中使用,来实现字符动画。

import cv2
import os
from PIL import  Image
import argparse


#命令行输入参数处理
parser = argparse.ArgumentParser()

parser.add_argument('file')     #输入文件
parser.add_argument('-o', '--output')   #输出文件
parser.add_argument('--width', type = int, default = 150) #输出字符画宽
parser.add_argument('--height', type = int, default = 80) #输出字符画高

#获取参数
args = parser.parse_args()

video = args.file
show_width = args.width
show_heigth = args.height

ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")

char_len = len(ascii_char)

def get_char(r,g,b,alpha = 256):
    if alpha == 0:
        return ' '
    length = len(ascii_char)
    gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
    #由于灰度大于字符 所以需要将灰度分配在不同的字符上
    unit = (256.0 + 1)/length
    return ascii_char[int(gray/unit)]

vc = cv2.VideoCapture(video)  # 加载一个视频

if vc.isOpened():  # 判断是否正常打开
    rval, frame = vc.read()
else:
    rval = False

frame_count = 0
outputList = []  # 初始化输出列表
num = 0
while rval:  # 循环读取视频帧
    if frame_count % 5 ==0:

        cv2.imwrite('%s.jpg'%('pic_'+str(num)),frame)
        name = 'pic_' + str(num)+'.jpg'

        im = Image.open(name)
        im = im.resize((show_width, show_heigth), Image.NEAREST)
        num += 1
        text = ""

        for i in range(show_heigth):
            for j in range(show_width):
                text += get_char(*im.getpixel((j,i)))#*可以传递元组
            text += '\n'
        outputList.append(text)

    frame_count = frame_count + 1
    rval, frame = vc.read()
print("处理完毕")

for frame in outputList:
    os.system("cls")  # 清屏
    print(frame)
    print()
    print()

知识点:对于cv2程序库有了一点点的认识,也算是自己单独去将图片转化成字符图升级成字符动画。

vc = cv2.VideoCapture(video)  #加载一个视频
rval , frame  = vc.read()            #读取视频的帧以及图像
cv2.imwrite(‘%s.jpg’%(‘pic_’+str(num)),frame) #将视频的图像以pic_’num’.jpg的形式保存

优化:

根据参考文献,知道了opencv可以直接将每一帧的图像转化成灰度图,然后通过resize以及get_char函数能够直接得到相对应的字符图

while rval:  # 循环读取视频帧
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # 使用opencv转化成灰度图
    gray = cv2.resize(gray, (show_width, show_heigth))  # resize灰度图
    text = ""
    for pixel_line in gray:
        for pixel in pixel_line:  # 字符串拼接
            text += ascii_char[int(pixel / 256 * char_len)]
        text += "\n"
    outputList.append(text)
    frame_count = frame_count + 1
    if frame_count % 100 == 0:
        print("已处理" + str(frame_count) + "帧")
    rval, frame = vc.read()
print("处理完毕")

 

 

参考文献:https://www.cnblogs.com/youmuchen/p/8299109.html

python小项目-图片转化成字符图

代码完成将一张图片转化成字符的图。
使用的程序库有 Pillow、argparse。
效果图如下:

思路:首先定义好命令行的参数,能够获取输入图片的路径、图片的长宽、以及输出的文件名;
之后定义能够将图片RGB值转化成之前设定好的字符串列表的函数;
遍历图片的每一个点,通过字符串保存所有的转化后的结果,并以txt格式输出。

# -*- coding=utf-8 -*-
from PIL import Image
import argparse

#命令行输入参数处理
parser = argparse.ArgumentParser()

parser.add_argument('file')     #输入文件
parser.add_argument('-o', '--output')   #输出文件
parser.add_argument('--width', type = int, default = 80) #输出字符画宽
parser.add_argument('--height', type = int, default = 80) #输出字符画高

#获取参数
args = parser.parse_args()

IMG = args.file
WIDTH = args.width
HEIGHT = args.height
OUTPUT = args.output

ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")

# 将256灰度映射到70个字符上
def get_char(r,g,b,alpha = 256):
    if alpha == 0:
        return ' '
    length = len(ascii_char)
    gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
    #由于灰度大于字符 所以需要将灰度分配在不同的字符上
    unit = (256.0 + 1)/length
    return ascii_char[int(gray/unit)]

if __name__ == '__main__':

    im = Image.open(IMG)
    im = im.resize((WIDTH,HEIGHT), Image.NEAREST) # Image.NEAREST表示输出低质量的图片

    txt = ""
    # 逐行遍历提取每个单位的RGB值
    for i in range(HEIGHT):
        for j in range(WIDTH):
            txt += get_char(*im.getpixel((j,i)))#*可以传递元组
        txt += '\n'

    print(txt)

    #字符画输出到文件
    if OUTPUT:
        with open("output.txt",'w') as f:
            f.write(txt)
    else:
        with open("output.txt",'w') as f:
            f.write(txt)

知识点:懂得了argparse库的一些函数的使用。
以及pillow库的使用。

if __name__ == ‘__main__’: 代码块中(表示如果 picture.py 被当作 python 模块 import 的时候,这部分代码不会被执行)。
parser.add_argument() 添加指令
Image.open() 打开图片
im.getpixel()  获得单位的RGB值
Image.NEAREST 输出低质量的图片

with 表达式为try-finally 的简写形式

####
格式
with context [as var]:
     pass
####
其中context是一个表达式,返回一个对象,var来保存context表达式返回的对象,可以存在一个或多个返回值

with open('1.txt') as f:
     print(f.read())

表达式open(‘1.txt’)返回一个io.TextlOWrapper类型的变量用f来接受。
在with语句块中就可以使用这个变量来操作文件。执行with之后,f会自动关闭相当于自带finally。
但是with本身没有捕获异常的功能,不论是否发生异常都会照常关闭文件。

优化:
由于之前通过保存在txt文件当中来进行查看图片是否转化成字符图,不仅有些许的繁琐,而且由于文本格式的问题会出现图像变形。所以了解了如何将字符图保存为图片的形式显示出来,所以添加了一些代码,使得在程序运行的时候就可以看到字符图,相较于打开文件来说方便了许多,也更加的直观。
实例如图:

from PIL import ImageDraw,ImageFont

    font = ImageFont.load_default()
    im_txt = Image.new('L', (WIDTH*8,HEIGHT*16), 255)
    d = ImageDraw.Draw(im_txt)
    d.text((0,0),txt,font = font)
    im_txt.show()
    im_txt.save('dog1.png')

 

参考文献:https://www.cnblogs.com/csnd/p/11526150.html

Python小项目–简易计算器

第一次尝试去做一个小的项目,去设计一个简易的计算器,能够实现加减乘除、回退、清零等步骤就可以了。

因此需要用到tkinter这个图形开发界面库,大致上了解了一下库中常用的一些函数如:button(按钮)、label(标签)等。

效果图如下:

思路:首先参考系统自带的计算器,对于整个计算器的框架、位置以及大小进行一个设置。讲整个计算器分为三个部分:显示部分、数字按钮、操作按钮。
显示部分用两个label来实现,一个用来显示整个计算过程,一个用来显示结果和数字。
数字按钮就是用来输入数字。
操作按钮就是用来执行操作如:AC、回退、+-*/=等操作

定义一个列表用来存储每次的按键以及一个用来判断是否按下符号的标志。
设置一个数字函数,判断是否按下数字按钮,并获取数字显示在显示器上。
设置一个操作函数,当按下操作按钮的时候,获取数字和符号,放入列表中。如果为’AC’,清零列表并将数字设置成默认值0.如果为’Back’,就将字符串回退一位。
当按下=时,将列表当中的字符串通过eval()来进行计算得出计算结果并输出到显示屏上面。

实例:

import tkinter as tk

root  = tk.Tk()
root.minsize(280,500)
root.title('计算器')

result1 = tk.StringVar()
result1.set(0)
result2 = tk.StringVar()
result2.set('')

label = tk.Label(root,font = ('微软雅黑',20),bg = '#EEE9E9',bd ='9',fg = '#828282',anchor = 'se',textvariable = result2)
label.place(width = 280,height = 170)
label2 = tk.Label(root,font = ('微软雅黑',30),bg = '#EEE9E9',bd ='9',fg = 'black',anchor = 'se',textvariable = result1)
label2.place(y = 170,width = 280,height = 60)


#数字键按钮

btn7 = tk.Button(root,text = '7',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda : pressNum('7'))
btn7.place(x = 0,y = 285,width = 70,height = 55)
btn8 = tk.Button(root,text = '8',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda : pressNum('8'))
btn8.place(x = 70,y = 285,width = 70,height = 55)
btn9 = tk.Button(root,text = '9',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda : pressNum('9'))
btn9.place(x = 140,y = 285,width = 70,height = 55)

btn4 = tk.Button(root,text = '4',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda : pressNum('4'))
btn4.place(x = 0,y = 340,width = 70,height = 55)
btn5 = tk.Button(root,text = '5',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda : pressNum('5'))
btn5.place(x = 70,y = 340,width = 70,height = 55)
btn6 = tk.Button(root,text = '6',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda : pressNum('6'))
btn6.place(x = 140,y = 340,width = 70,height = 55)

btn1 = tk.Button(root,text = '1',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda : pressNum('1'))
btn1.place(x = 0,y = 395,width = 70,height = 55)
btn2 = tk.Button(root,text = '2',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda : pressNum('2'))
btn2.place(x = 70,y = 395,width = 70,height = 55)
btn3 = tk.Button(root,text = '3',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda : pressNum('3'))
btn3.place(x = 140,y = 395,width = 70,height = 55)
btn0 = tk.Button(root,text = '0',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda : pressNum('0'))
btn0.place(x = 70,y = 450,width = 70,height = 55)

#运算符号按钮
btnac = tk.Button(root,text = 'AC',bd = 0.5,font = ('黑体',20),fg = 'orange',command = lambda :pressCompute('AC'))
btnac.place(x = 0,y = 230,width = 70,height = 55)
btnback = tk.Button(root,text = '←',font = ('微软雅黑',20),fg = '#4F4F4F',bd = 0.5,command = lambda:pressCompute('b'))
btnback.place(x = 70,y = 230,width = 70,height = 55)
btndivi = tk.Button(root,text = '÷',font = ('微软雅黑',20),fg = '#4F4F4F',bd = 0.5,command = lambda:pressCompute('/'))
btndivi.place(x = 140,y = 230,width = 70,height = 55)
btnmul = tk.Button(root,text ='×',font = ('微软雅黑',20),fg = "#4F4F4F",bd = 0.5,command = lambda:pressCompute('*'))
btnmul.place(x = 210,y = 230,width = 70,height = 55)
btnsub = tk.Button(root,text = '-',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda:pressCompute('-'))
btnsub.place(x = 210,y = 285,width = 70,height = 55)
btnadd = tk.Button(root,text = '+',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda:pressCompute('+'))
btnadd.place(x = 210,y = 340,width = 70,height = 55)
btnequ = tk.Button(root,text = '=',bg = 'orange',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :pressEqual())
btnequ.place(x = 210,y = 395,width = 70,height = 110)
btnper = tk.Button(root,text = '%',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda:pressCompute('%'))
btnper.place(x = 0,y = 450,width = 70,height = 55)
btnpoint = tk.Button(root,text = '.',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda:pressCompute('.'))
btnpoint.place(x = 140,y = 450,width = 70,height = 55)


lists = []
isPressSign = False


#数字函数
def pressNum(num):
    global lists
    global isPressSign
    if isPressSign == False:
        pass
    else:
        result1.set(0)
        isPressSign = False

    oldnum = result1.get()
    if oldnum =='0':
        result1.set(num)
    else:
        newnum = oldnum + num
        result1.set(newnum)


#运算函数

def pressCompute(sign):
    global lists
    global isPressSign
    num = result1.get()
    lists.append(num)

    lists.append(sign)
    isPressSign = True

    if sign =='AC':
        lists.clear()
        result1.set(0)
    if sign =='b':
        a = num[0:-1]
        lists.clear()
        result1.set(a)

#获取运算结果
def pressEqual():
    global lists
    global isPressSign


    curnum = result1.get()
    lists.append(curnum)

    computrStr = ''.join(lists)
    endNum = eval(computrStr)

    result1.set(endNum)
    result2.set(computrStr)
    lists.clear()

root.mainloop()

通过自身的查找文章,以及查阅博客,大致上能够代码复现出来。也算是第一次完成了一个小项目。大概了解关于tkinter的相关知识

参考文献:https://www.cnblogs.com/sunshine-long/p/7902721.html

Python函数

函数是组织好了的、可以重复使用的代码段,提高了代码的重复利用率。

定义一个函数
规则:
1. 函数代码以def关键字开头,后接函数标识名称和圆括号()
2. 所有传入参数和自变量在圆括号中间。
3. 函数第一行可以用来选择性的使用文档字符串用于函数说明
4. Return 作为结束,返回一个值作为调用方,

函数调用
定义一个函数只给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从Python提示符执行。

参数传递
在python中,类型属于对象,变量是没有类型的。
如:a = [1,2] 其中[1,2]是list的类型,而变量a是没有类型的,它仅仅是一个对象的引用(一个指针),可以指向任何的对象.
在python中,字符串、整数、元组是不可更改的;列表,字典是可更改的。
不可变:类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
可变:类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响
用一句话来说讲:就是传递不可变对象和可变对象的区别。
实例:

def Change(a):
    a = 10
def change(a):
    a.append(10)
    
a = 2
b = [2]
Change(a)
change(b)
print(a)
print(b)

output:
2
[2,10]

参数
调用函数时可使用的参数类型:
必备参数、关键字参数、默认参数、不定长参数。
必备参数:必须以正确的顺序传入函数。调用的数量和声明的要一样。
关键字参数:通过使用关键字参数来确定传入的参数值。(顺序可以不一致)
默认参数:在定义函数的过程中会先设定好一些参数,若调用时没有传入就认为默认值。
不定长参数:处理比当初声明时更多的参数时,多出来的就是不定长参数。
实例:

def printf(str,*var,n=1):
    for i in range(n):
        print(str)
    for a in var:
        print(a)

printf("s")
print("-----")
printf("s",n=3)
print("-----")
#printf(n=3,"s")
printf("s",1,50)
print("-----")
printf("s",50,n=1)

output:
s
-----
s
s
s
-----
s
1
50
-----
s
50

Tips:关键字参数需要放在参数的最后面(不论是传入还是定义的时候);当出现不定长和默认参数时需要注意两者之间的顺序等很容易出错。

匿名函数 lambda
简单版的def 简化了行数
语法:
Lambda 【a,b】:expression
实例:

sum = lambda a,b : a+b
print(sum(10,20))

全局变量和局部变量
局部变量只能在被声明的函数内部访问,而全局变量可以在整个程序内访问。
实例:

a = 1
def sum(arg1,arg2):
    a = arg1 + arg2
    return a

def sum1(arg1,arg2):
    global  a
    a = arg1 + arg2
    return a
print(sum(2,1))
print(a)
print(sum1(2,1))
print(a)

output:
3
1
3
3

tips:在函数内使用全局变量时,需要先在函数中声明global。

参考链接:https://www.runoob.com/python/python-functions.html

Python 面对对象:类的使用

类:用来描述具有相同属性和方法的对象集合。它定义了该集合中每个对象所共有的属性和方法,对象是类的实例。

类的创建
使用class 语句来创建一个新类, 名称后面冒号结尾
实例:

class Employee:
    empCount = 0
    def __init__(self,name,salary):
        self.name = name
        self.salary = salary
        Employee.empCount += 1

    def displayCount(self)
        print("Total Employee %d" % Employee.empCount)

a  = Employee("a",600)
b  = Employee("b",700)
c  = Employee("c",600)

b.displayCount()

其中empCount 为类变量,这个值在这个类的所有实例之间是共享的,也可以通过内部类、外部类来访问。
__init()被称为类的构造函数或者理解成初始化方法,可以理解成为自己输入你想要的属性,通过括号中输入你想要的属性
其中每个类中都会出现self这个东西,它代表类的实例,self在定义类的方法时必须存在。
a = Employee(‘a’,600) 实例化 通过init来接受参数

类的继承
作为面对对象中最为关键的一个功能,就是代码可以重用,而重用就是通过继承来实现的。
继承语法
Class 子类名(父类)
继承中的一些特点:

    1. 在调用父类的方法时,需要加上父类的类名前缀,且要带上self参数变量。
    2. Python首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。
    3. 如果子类需要用到父类的构造函数,直接使用就可以,不需要自己在重新去写。

实例:

class Employee: 
      empCount = 0 
      def __init__(self,name,salary): 
          self.name = name 
          self.salary = salary 
          Employee.empCount += 1 

      def displayCount(self) 
          print("Total Employee %d" % Employee.empCount) 

class employer(Employee)
      def __init__(self)
          print("调用子类构造函数")
      def method(self):
          print("调用子类方法")

c = employer() 
c.method() 
c.displayCount() 
print(c.empCount)

ouyput:
调用子类构造函数
调用子类方法
Total Employee 0
0

方法重写
如果你觉得父类的方法功能不太适合子类,可以通过在子类中重写父类的方法,来满足子类自身的需求。

类的属性与方法
类的私有属性
__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被访问使用。在内部的使用方法为self.__private_attrs
类的私有方法
__private_method: 同样两个下划线的开头,声明该方法为私有方法,不能外部调用。内部调用self.__private_methods
实例:

class Employee:
    empCount = 0
    __secretCount = 0
    def __init__(self,name,salary):
        self.name = name
        self.salary = salary
        Employee.empCount += 1
        Employee.__secretCount += 1

a  = Employee("a",600)
b  = Employee("b",700)
c  = Employee("c",600)

print(a.empCount)
#print(a.__secretCount)

print(a._Employee__secretCount)

会产生报错,实例不可以访问私有变量
实在想要去访问的话可以使用 object._className__attrName(对象名._类名__私有属性名)
例:print(a._Employee__secretCount)

单下划线、双下划线、头尾下划线的说明
头尾下划线主要为为一些系统定义的名字
单下划线表示为protected类型的变量,即保护类型只能允许其本身与子类访问
双下划线表示为private 类型变量,只允许这个类本身访问

面对对象的理解

由于python是一门面对对象的语言,所以在学习的过程中对于面对对象的不理解,对此进行相应的了解并记录。

面对对象:不需要去更改已经测试好了的既有类。它有着良好的灵活性以及扩展性,能够适应不同的变化。他与面对过程不一样的地方在于通过继承、封装、多态化,可以在保持原有代码不变的情况下去在这个基础上增加一些附加的内容。而面对过程需要去选择更改源代码来进行附加内容。
封装:将客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类继承或操作,不可信的隐藏。
继承:可以理解成新类去继承老类的所有功能,在不用编写原来类的情况下对其进行一定程度上的扩展。通过继承创建的新类被称为子类或派生类,被继承的类被称为父类或者基类。
多态化:允许你将父对象设置称为和一个或者更多的他的子对象相等的技术,赋值之后,父对象可以根据当前赋值给它的子对象的特性以不同的方式运作。简单说就是一句话:龙生九子各有不同,每个孩子的不同就是多态。实现多态,有两种方式,覆盖和重载。两者的区别在于:覆盖在运行时决定,重载是在编译时决定。并且覆盖和重载的机制不同。
换个例子来理解面对对象和面对过程:古代的活字印刷以及雕版印刷的区别。一个可以通过一个个的小字来拼凑出一篇文章,较为灵活另一个则需要通过雕刻一版的文章中间不能出现任何的差错。

Python中队列Queue

Queue是python库中的队列实现,提供了不同的队列数据结构。

其中一共有四种队列模型:

  • Queue  先进先出型
    import Queue
    q = Queue.Queue()
    for i in range(5):
        q.put(i)
    while not q.empty():
        print q.get()
    
    output:
    0
    1
    2
    3
    4
  • LifoQueue 先进后出型
    import Queue
    q = Queue.LifoQueue()
    for i in range(5):
        q.put(i)
    while not q.empty():
        print q.get()
    
    output:
    4
    3
    2
    1
    0
  • PriorityQueue 优先型
    import queue
    pq = queue.PriorityQueue(maxsize=0)
    pq.put((9,'a'))
    pq.put((7,'c'))
    pq.put((1,'d'))
    print(pq.queue)
    pq.get()
    pq.get()
    print(pq.queue)
    
    output:
    [(1, 'd'), (9, 'a'), (7, 'c')]
    [(9, 'a')]
  • deque 双边型
    dq = deque(['a','b'])
    dq.append('c')
    dq.appendleft('d')
    print(dq)
    print(dq.pop())
    print(dq.popleft())
    
    output:
    deque(['d', 'a', 'b', 'c'])
    c
    d