基础内容

标识符

由字母、数字、下划线组成,也可以使用中文作为标识符,不能以数字开头,且不能使用关键字

关键字如下

andasassertbreakclasscontinuedefdel
elifelseexceptexecfinallyforfromglobal
ifinimportislambdanotorpass
printraisereturntrywhilewithyield

变量的类型可以随意进行变化,python是动态类型语言

使用type(变量名)查看变量类型

id()用法

使用id(变量名)查看变量地址

python在赋值时,将值所在的地址赋给了变量

>>> a=1
>>> b=1
>>> id(a)
140719959342144
>>> id(b)
140719959342144
>>> id(1)
140719959342144

但由于python解释器问题,将-5-256之间的数字放到小整数对象中,使其引用时方便,而大于这个数的值会另外分配,提高了效率

>>> id(a)
1477726164048
>>> id(b)
1477726164016
>>> id(257)
1477726164176

输入输出函数

输入input()

从键盘以及标准输入流中读入一个字符串,即输入的内容被当作字符串处理

读入时可以使用强制类型转换,例如转换为整型的写法为

a = int(input())

还可在输入前给出提示

a = input("内容")

####split()函数

若想在一行得到多个字符串(以空格分割),可以使用split()

split含义为分割

a,b=input().split()

输出print()

print函数输出内容时默认带有换行符,但也可以去除

print(内容,end="")

end后的内容可以是任意值,并在输出内容时,在其末尾会带有相关的内容

语句

赋值

####基本赋值

变量 = 值

####序列赋值

赋值有多种形式,可以使用序列赋值

a,b = "34"

此时a='3',b='4'

a,b = 4444,5555

此时a=4444,b=5555

####多变量赋值

a = b = c = 4;

此时三者的值都是4

简单的变量交换

a = 1
b = 2
#若要交换两者的值
a, b = b, a

分割赋值

a, *b=[1,2,3,4,5]

此时a为1,b为[2,3,4,5]

if语句

语法格式

if 逻辑表达式:
    语句块
else:
    语句块

条件表达式





## for语句

### 语法

​```python
for xxx:
    语句块;

range()函数

range(start, stop, step)

  • 开始值,默认为0

  • 结束值,必备的

  • 步长,默认为1

列表推导式

格式

变量1=[循环变量表达式 for 循环变量 in range()]

例如

a = [2 * n for n in [1,2,3,4]]

此时a为[2, 4, 6, 8]

也可以添加条件判断

 a=[i for i in range(8) if i % 2 ==1 ]

此时a=[1,3.5.7]

产生一个字符串序列

["6" * i for i in range(1, 10)]

序列为

['6', '66', '666', '6666', '66666', '666666', '6666666', '66666666', '666666666']

也可以生成整形的

[int("6" * i) for i in range(1, 10)]

序列为

[6, 66, 666, 6666, 66666, 666666, 6666666, 66666666, 666666666]

格式化输出

容器

在python中,字符串和列表都可以被看成一个容器

序列

字符串和列表也是一个序列

  • 序列都可以通过相加进行连接,通过乘以某个整数进行复制

  • 序列也可以通过数字下标进行索引,正向索引值都是从0开始,如果超出范围,会抛出异常,反向索引从-1开始,-1代表其最后一个元素

  • 序列可以通过in或者not in判断是否在/不在序列中

  • 列表中,可以通过下标进行修改值,字符串不支持修改,会抛出异常

  • 序列也支持切片操作,格式为变量[start:end],此时会取出从startend-1之间的值,start和end可以省略,省略start代表从头开始,省略end,代表到末尾

  • 都可以使用全局函数len(变量名)计算长度,使用min(变量名)或者max(变量名)计算最大值和最小值,如果是字符串,会按照Unicode进行排序

  • 如果字符串中包含"或者'其中一个时,可以使用'或者"进行字符串进行赋值,也可以使用转义字符,只需要添加\即可

  • 也可以不加转义字符,直接在赋值时进行操作,即所见即可得

    a='''
    内容
    '''
    
    #或者
    a="""
    内容
    """
    
  • 续行,续行的标志是在一行的末尾添加\

  • 也可以在赋值前添加r,添加r后,一行中的转义字符不会被当作转义字符进行解释

字符串函数

函数含义
s.lower()降低,转为小写
s.upper()提升,转为大写
s.find(字符串,开始位置,结束位置)查找子串,从左边开始查找,找到则返回第一个字母的位置,找不到返回-1,开始位置或者结束位置参数可以省略
s.count(字符串)查看某个字符串在该字符串出现的次数
s.strip()去掉两端的所有的空格,如果是s.lstrip()则去掉左边的,如果是s.rstrip()则去掉右边的
s.replace(字符串1,字符串2)返回将字符串中的所有与字符串1一致的字符替换成字符串2后的值,原字符串不会被修改

in也可以查看是否是子串,但不会返回位置,只返回True或者False

以上的函数均不会直接修改s的值

列表

列表中的元素可以是不同类型,使用[]表示,元素之间使用,分割,也属于序列,序列所有的操作,列表也有,列表是动态的

可以使用list(变量)进行转换成列表,字符串转换成列表后,其中的每个字符都是一个新的列表项(item)

Python中,列表变量是列表的管理者,而并非所有者

>>> a=[x for x in range(10)]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b=a
>>> b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[0]=999
>>> a
[999, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b
[999, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b[7]=7777
>>> b
[999, 1, 2, 3, 4, 5, 6, 7777, 8, 9]
>>> a
[999, 1, 2, 3, 4, 5, 6, 7777, 8, 9]

此时使用一个变量引用并修改其中的一个值,两个变量中的这个值都会被改变

列表直接的赋值是让一个列表进行管理另一个列表,而并非直接将这个列表中的值完全赋给另一个列表

####切片应用

如果想要使一个变量管理整个列表时不影响另一个,除了复制之外,还可以切片

a = [x for x in range(99)]
b = a[:]

也可以进行切片赋值

>>> a=[i for i in range(10)]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[3:6]=[333,444,555]
>>> a
[0, 1, 2, 333, 444, 555, 6, 7, 8, 9]
>>>

变量名[开始值:结束值]=[值1,.....值n],如果修改值的列表长度正好与被修改的范围相同,那么,值会一一替换,如果小于,则将会以被修改的部分为基准进行赋值,没有的部分将删除

####del使用

可以使用del(变量名[下标])或者del 变量名[下标]进行删除该下标处的元素

>>> a=[i for i in range(10)]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del(a[1])
>>> a
[0, 2, 3, 4, 5, 6, 7, 8, 9]

#或者
del a[3]

列表操作函数

函数含义
a.append(值)附加,末尾添值,如果为列表,则整个列表作为一个元素添加到尾部,即列表嵌套列表
a.extend(列表)扩展,将一个列表合并到a的尾部,与a+=[item]作用效果相同
a.insert(位置,值)位置前添加一个,如果值为列表,则也会将列表作为一个元素插入进去,如果位置超过最大下标,则会将值插入到最后的位置,如果小于最小位置的负值,则会插入到头部
a.remove(值)会删除第一个与值所匹配的元素
a.pop(位置)删除a[位置]的元素并返回其值,参数可以省略,省略后返回最后一个元素并删除
a.reverse()逆转,相反,撤销,翻转列表
a.index(值)返回值在a中的第一次出现的具体位置,如果不在列表中,则抛出异常

字符串和列表间的操作

split()函数

split 分裂

执行s.split()后,会将字符串以空格的形式进行分割,返回每个单词单独作为字符串的列表

split(字符串),也可以带有一个字符串作为参数,作用是以该参数作为分隔符

#####join()函数

可以看作是split()的逆行操作,用于将列表中的字符串重新组成一个新的字符串

用法

字符串/字符串变量.join(列表变量)

其中第一个字符串的作用是作为两个字符串之间的连接符

元组tuple

使用圆括号进行表示

a = ()

与列表基本性质一致,特点是元组内的值无法被修改

在python中,只要是用,进行分割的元素,在不添加{}[]""''等限定符时,默认时被当作元组处理的

例如,以下为等价的

>>> a=3,4,5,6,7,8,8,4,245,5>>> a(3, 4, 5, 6, 7, 8, 8, 4, 245, 5)>>> a=(3,4,5,6,7,8,8,4,245,5)>>> a(3, 4, 5, 6, 7, 8, 8, 4, 245, 5)

排序sort()

可以用sort进行排序

条件语句

if 条件:    语句块else:    语句块

以缩进代表从属于

级联的if语句

if 条件:
    语句块
elif 条件:
    语句块
else:
    语句块

循环语句

while 条件:
    语句块

可以使用break跳出循环

for 语句:
    语句
for 语句:
    语句
else:
    语句

含义为如果for正常退出,即没有遇到for循环中的break时会执行else


异常

python有专门针对异常的语句

try:
    语句
except:
    语句

except中文:除了

可以有多个句子,是一种保护机制,在程序抛出异常后不会直接退出程序

try:
    语句
except 异常类型1:
    语句
except 异常类型2:
    语句
except 异常类型n:
    语句
except:
    语句
else:
    语句
finally:
    语句
  • try中没有出现任何异常,执行else
  • 无论如何都会执行finally

###异常类型

>>> 5/0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

以上语句中的异常类型为ZeroDivisionError

集合set

  • 集合当中没有重复的元素
  • 可以执行交、并、补运算
  • 集合是无序容器,即无法指定数据在集合中的位置
  • 集合是可变的
  • 字典、集合共用{}表示,默认情况下,{}表示字典,即要想创建集合,必须使用set()

###创建

s = set()

操作函数

函数含义
s.add(值)向集合添加元素
s.remove(值)删除元素
len(s)计算集合的长度
min(s)求集合中最小的元素
max(s)求集合中最大的元素
sum(s)求和
值 in s判断是否在内
值 not in s判断是否不在内
  • 可以使用for...in...进行遍历输出和访问
  • 两个集合可以使用==进行判等操作,即看元素是否全部相同
  • 集合1 < 集合2判断集合1是否为集合2的真子集
  • 集合1 <= 集合2判断集合1是否为集合2的子集

交并补

符号含义
&交集,即两个集合共有的
|并集,即两个集合所有的
^对称差,将两个集合取并集,去除两者共有的,即不为两者同时共有的元素
-差集,即去掉另外集合中有的元素

字典dict

  • 形式key:value,即键:值
  • 可以通过变量名[key]获取键中的值
  • 如果试图访问一个不存在的键时,会直接抛出异常
  • 添加元素时,可以直接使用变量名[key] = value进行赋值,也可以通过此方式直接修改值
  • 删除元素时,直接使用del 变量名[key]进行删除,如果key不存在时,直接抛出异常
  • 不能使用位置进行遍历,可以使用for...in...遍历字典的key,再通过变量名[key]访问值
  • 可以通过max(变量名) min(变量名)获取最大/最小的key
  • 获取值也可以通过get(值)获取,与直接使用索引方式获取的区别是:当key不存在时不会抛出异常

get()

形式

d = {}
d.get(key) #该key存在时返回key,不存在返回none
d = {}
d.get(key,value) #该key存在时返回key,不存在返回value

官方文档解释

Return the value for key if key is in the dictionary, else default.

如果key在字典中,则返回key的值,否则返回默认值。

函数

基本形式

def 函数名(参数列表):
    函数体

定义要在执行之前

###lambda表达式

lambda为匿名表达式,经常用来编写简单的函数

基本形式

函数名 = lambda 参数列表:返回值

参数

位置参数:严格按照函数给定的位置进行参数赋值

关键字参数:为了避免严格的参数位置要求,Python函数的参数的位置是可变的

def fun(x,y,z):
    return x + y + z;
#调用
fun(y = 1,z = 3,x = 3)

当两者同时出现时,先写关键字参数,再写位置参数

def fun(x,y,z):
    return x + y + z;
#位置参数+关键字参数
fun(1,z = 3,y = 3)

默认值参数:当调用时未提供相应位置参数时,以默认值代替该位置的参数,若提供了实参,则使用实参进行代替

def fun(x=1,y=2,z=3):
    return x + y + z;
#位置参数+关键字参数
fun(9) #等价于fun(9, 2, 3)

数量可变参数:

  • 当函数参数数目不确定时,可以使用*变量名的方式接收值,此时该位置的参数将会放在一个元组中

    def fun(x, *y):
        print(y)
    fun(1, 2, 3, 4, 5, 6, 7, 8, 9)
    # 此时元组y中的值为(2, 3, 4, 5, 6, 7, 8, 9)
    
  • 当存在两个星号,即**变量名时,表示将参数放入到字典中

    def fun(x, **y):
        print(y)
    
    
    fun(1, a2=3, a3=5, a4=6)
    # 此时字典y的值为{'a2': 3, 'a3': 5, 'a4': 6}
    
  • 实参拆包,当输出时加上*会把多个可变参数逐一输出

    def fun(x, *y):
        print(*y)
    fun(1, 2, 3, 4, 5, 6, 7, 8, 9)
    # 输出的值为2 3 4 5 6 7 8 9
    
    
    def fun(x, **y):
        print(*y)
    
    
    fun(1, a2=3, a3=5, a4=6)
    # 此时输出值为a2 a3 a4,即字典的key
    

    当实参为不可变的对象参数时,形参不会影响实参

    当实参为可变对象参数时,形参可能影响实参

返回值

  • 函数使用return语句返回值
  • return后边的表达式值即为此次函数调用的返回值
  • 如果函数没有用return语句返回,此时函数返回None,若return后没有表达式,返回值也为None
  • NonePython中特殊的返回值
  • 返回值不只是可以返回数值,还可以返回函数

变量作用域(命名空间)

Python中,赋值即被定义

全局变量:定义在函数外,作用域是整个程序

局部变量:定义在函数内,作用域是函数内部,形参也是局部变量

若想要在函数内使用全局变量(而不是创建全局变量),可以使用global进行声明

def fun():    global a    print(a)a = 333# 此时如果在函数内修改了a的值,其外部的a的值也会被修改

内置函数

sorted

  • sorted可以对元组、列表、字符串、字典等进行排序操作
  • sort仅可以对列表进行操作,sort是对已经存在的列表进行操作,而sorted仅返回一个新的排序后的序列,不会对原有的进行操作
格式
sorted(iterable, /, *, key=None, reverse=False)
    Return a new list containing all items from the iterable in ascending order.

    A custom key function can be supplied to customize the sort order, and the
    reverse flag can be set to request the result in descending order.
    返回一个新列表,其中包含迭代中所有项目的升序排列。

    可以提供自定义键功能以自定义排序顺序,然后
    可以设置反向标志以按降序请求结果

sorted(迭代序列, 排序规则函数, 升序(False 默认)/降序(True))

排序规则函数通常使用lambda表达式

a = [3, 43, 5, 5476, 746, 2]
# 对a进行升序排序
>>> sorted(a)
[2, 3, 5, 43, 746, 5476]

>>> sorted(a, reverse = False)
[2, 3, 5, 43, 746, 5476]

>>> sorted(a, key=lambda x : x)
[2, 3, 5, 43, 746, 5476]



# 对a进行降序排序
>>> sorted(a, reverse = True)
[5476, 746, 43, 5, 3, 2]

>>> sorted(a, key = lambda x : -x)
[5476, 746, 43, 5, 3, 2]




# 多个参数
info = [{"name": "admin1", "age": 81, "height": 12}, {"name": "admin2", "age": 34, "height": 254},
        {"name": "admin3", "age": 24, "height": 45}]
print(sorted(info, key=lambda x: (-1 * x["name"], x["age"], x["height"])))

a = {1, 3, 45, 4376, 764, 7, 578, 4, 3, 63, 63}
print(sorted(a, key=lambda x: -x))

map()函数

map()函数会对指定的序列做一个映射

语法

  • map(函数,序列)
  • 第一个函数可以为lambda表达式,每个元素都调用函数的返回值
  • 函数的返回值为新的列表或者迭代器
>>> a
{2, 3, 5476, 5, 746, 43}
>>> list(map(lambda x:x**2,a))
[4, 9, 29986576, 25, 556516, 1849]

以上为求a中的所以有元素的平方,其中的序列也可以是多个,若序列长短不一,则以最短的为基准

# 多个序列
>>> a = b = [i for i in range(10)]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(map(lambda x, y:x + y, a,b))
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

zip()函数

将多个序列打包成一个元组

>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(zip(a,b))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9)]
# 如果长短不一,y
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> c
[0, 1, 2, 3, 4, 5, 6, 7]
>>> list(zip(a,c))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7)]

程序结构

###import引入

# 一个python程序可能是在不同的文件中,这些文件就是一个个小的模块,可以使用import引入
import 模块名
# 引入模块的另一种方式
from 模块名 import * #引入模块中所有的函数,调用时不需要再添加模块名
from 模块名 import 函数名 #引入模块的单个函数,调用时也无需添加模块名

例如数学模块

  • 引用方式1
import math
# 在math中有一个sin()函数,函数返回一个值,如果使用此方法引入,调用sin()的过程为
math.sin(x)
  • 引用方式2
from math import *
sin(x)
  • 引用方式3
from math import sin
sin(x)

可以自己编写相应的模块,例如

main.py

import test

x = 4
print(test.fun(x))
#输出16

test.py

def fun(x):
    return x ** 2

主程序也有模块名,主程序的模块名是__main__

也可以使程序更具有扩展性,可以把多个模块文件放在一个目录底下,使其组织成一个包,如果模块存在于包中,可以使用import 包名.模块名.函数名,调用时可以采用包名.模块名.函数名

面向对象

目的是实现代码复用和设计复用,提高开发的效率

类是一种对象模板和数据类型,定义了对象的属性,提供了初始化对象的初始化程序和方法

对象

对象是类的一个实例,使用构造方法来创建一个对象,使用.运算符引用方法和变量访问对象成员

对象(object)=实例(instance)ˈinstəns


面向对象的特性是封装、继承、多态

类的定义

类名遵循大驼峰命名规则

class 类名:
    语句

类中定义方法

class 类名:
    def 方法名(self,参数列表):
        语句

类中定义的方法,第一个参数必须是self

哪一个变量调用了方法,self就为哪个变量的引用,如果要在类中使用变量的成员属性时,可以使用

self.成员变量
# 与Java中的

例如

class 类名:
    def 方法名(self):
        语句
a = 类名()
a.方法名()

此时方法名中的self为对象变量a的引用

创建对象

对象变量 = 类名()

####案例

  • 小猫爱吃鱼
  • 小猫爱喝水

这两句话共同的对象是小猫

class Cat:
    def eat(self):
        print("小猫爱吃鱼")

    def drink(self):
        print("小猫爱喝水")


cat = Cat()
cat.eat()
cat.drink()
# 输出结果
# 小猫爱吃鱼
# 小猫爱喝水

主程序中只需要让方法工作,不再关心方法的内部细节

class Cat:
    def eat(self):
        print("小猫爱吃鱼")

    def drink(self):
        print("小猫爱喝水")
cat = Cat()
tom = Cat()
print(id(cat))
print(id(tom))
"""
输出结果
2175638454664
2175638454792
"""

此时tomcat不是同一个对象

class Cat:
    def eat(self):
        print("小猫爱吃鱼")

    def drink(self):
        print("小猫爱喝水")


cat = Cat()
jack = cat
print(id(cat))
print(id(jack))
"""
1960610775368
1960610775368
"""

而此时的jackcat是同一个对象,相当于拷贝构造

python中也允许临时增加属性

class Cat:
    def eat(self):
        print("小猫爱吃鱼")

    def drink(self):
        print("小猫爱喝水")


cat = Cat()
jack = Cat()
cat.name = "cat"

此时只是给对象变量cat临时增加了一个name属性,而jack并没有被增加,该方式被不推荐


####初始化方法(构造方法)

当使用变量 = 类名()创建对象时,会执行以下操作

  • 为对象在内存中分配一块空间,即创建对象
  • 为对象的属性进行初始化值,即自动执行初始化方法__init__()
  • __init__()方法是专门定义一个类具有哪些属性的方法
class Cat:
    def __init__(self):
        print("这是创建对象后默认执行的方法")


cat = Cat()

这段代码执行后,会自动执行__init__()函数,从而直接输出这是创建对象后默认执行的方法__init__()函数常用来定义成员变量的默认属性

定义方式为self.变量名 = 值

class Cat:

    def __init__(self):
        print("这是创建对象后默认执行的方法")
        self.name = "cat"


cat = Cat()
print(cat.name)

以上可以理解为无参构造,python也可以进行有参构造

class Cat:
    def __init__(self, new_name="无名字"):
        self.name = new_name


cat = Cat()
print(cat.name)

tom = Cat("tom")
print(tom.name)

"""
输出结果为
无名字
tom
"""

以上就属于有参构造,原理就是在__init__()函数中添加相应参数,使得成员变量在进行属性设置时进行赋值

销毁方法

销毁方法与初始化方法相对应,销毁方法是一个对象在内存中被销毁时所执行的方法

  • 销毁方法使用__del__()进行表示
class 类名:
    def __init__(self):
        语句
        
    def __del__(self):
        语句
        
变量 = 类名()        

程序运行结束时会释放所有的类,此时会执行__del__方法

使用del 对象变量时也会执行__del__方法

__str__()方法

在python中,使用print()函数进行输出时默认是输出这个变量引用的对象是由哪个类创建的对象以及内存地址

如果希望在输出这个变量时,输出自己想要的效果,可以使用__str__方法,__str__方法必须返回一个字符串

封装

  • 封装是面向对象的一大特点
  • 首先将属性方法封装到一个抽象的类中
  • 外界使用创建对象,使用对象调用方法
  • 对象方法的细节被封装在类中
  • 方法中的形参命名不影响类内的成员变量的命名,即方法的形参命名可以和类内成员变量命名相同
  • 同一个类中,两个不同的对象不会相互影响
  • 一个对象的属性可以是另一个类创建的对象
  • 如果不确定初始值时,可以设置为None
  • 变量1 is 变量2判断两个地址是否相同,等价于id(变量1)==id(变量2)
  • 变量1 is not 变量2判断两个地址是否相同,等价于id(变量1) != id(变量2)

案例 跑步

  • XX的体重是XX公斤
  • XX每次跑步会减少0.5公斤
  • XX吃一次东西增加1公斤
class Person:
    def __init__(self, name, weight):
        self.name = name
        self.weight = weight

    def run(self):
        self.weight -= .5

    def eat(self):
        self.weight += 1

    def __str__(self):
        return self.name + "体重是" + str(self.weight)


xiaoMing = Person("小明", 77)
xiaoMing.eat()
xiaoMing.run()
print(xiaoMing)

私有属性和私有方法

  • 某些属性方法只希望在对象内部进行使用,不希望在外部访问到

  • 属性/方法名前加两个下划线就会变成私有的

  • python中没有真正意义上的私有,私有的成员变量也可以想办法访问

    对于对象外私有属性和私有方法的引用,在前面添加_类名即可

class Woman:
    def __init__(self, name):
        self.name = name
        self.__age = 10

    def secret(self):  # ˈsēkrit
        print(self.name + "年龄是" + str(self.__age))


xiaoHong = Woman("小红")
print(xiaoHong.__age)
xiaoHong.secret()

此时这段代码会报错,问题出现在11行,age是一个私有属性

class Woman:
    def __init__(self, name):
        self.name = name
        self.__age = 10

    def __secret(self):  # ˈsēkrit
        print(self.name + "年龄是" + str(self.__age))

    def test(self):
        self.__secret()


xiaoHong = Woman("小红")
# print(xiaoHong.__age)
xiaoHong.__secret()
xiaoHong.test()

此时这段代码也会报错,15行的内容出错,secret方法是私有的,对象外部不能直接访问

解决办法(开发中不建议使用此方法访问私有属性和方法)在前面添加_类名即可

class Woman:
    def __init__(self, name):
        self.name = name
        self.__age = 10

    def __secret(self):  # ˈsēkrit
        print(self.name + "年龄是" + str(self.__age))

    def test(self):
        self.__secret()


xiaoHong = Woman("小红")
print(xiaoHong._Woman__age)
xiaoHong._Woman__secret()
xiaoHong.test()

继承

继承实现代码的复用,相同的代码不需要重复的编写,子类继承父类的公共属性,无法继承私有属性

语法

class 类名(父类名):
    语句
class Animal:
    def __init__(self, Name):
        self.name = Name

    def drink(self):
        print(self.name + "正在吃")

    def run(self):
        print(self.name + "正在跑")

    def sleep(self):
        print(self.name + "正在睡")

    def __secret(self):
        print("秘密哟")


class Dog(Animal):
    def call(self):
        print("汪汪汪")



dog = Dog("狗")
dog.run()
dog.sleep()
dog.drink()
dog.call()

####专业术语

在以上代码中

  • dog类是Animal类的子类Animal类是Dog类的父类dog类是从Animal类的继承
  • dog类是Animal类的派生类Animal类是Dog类的基类dog类是从Animal类的派生

继承的传递性

继承具有传递性,子类拥有父类以及父类的父类方法属性

方法重写

当父类的方法实现无法满足子类的需求时,可以对对方法进行重写,重写的意思为重新编写

重写方法有两种情况

  • 覆盖父类的方法

    直接在父类中定义一个与父类中重名的一个方法,即可进行重写

  • 对父类进行扩展

    • 子类中重写父类方法名
    • 在需要的位置使用super().父类方法调用父类的执行
    • 其他位置根据需要,编写子类的特定的代码实现

在python中super()是一个特殊的类,super()时使用super类创建出来的对象

class Animal:
    def __init__(self, Name):
        self.name = Name

    def drink(self):
        print(self.name + "正在喝")

    def run(self):
        print(self.name + "正在跑")

    def sleep(self):
        print(self.name + "正在睡")

    def __secret(self):
        print("秘密哟")


class Dog(Animal):
    def call(self):
        print("汪汪汪")

    def drink(self):
        print("狗不渴")
        super().drink()#此处为扩展



dog = Dog("狗")
dog.run()
dog.sleep()
dog.drink()
dog.call()

父类的私有属性和私有方法

  • 类的私有属性、私有方法是对象的的隐私,不会对外公开,只能类内访问,类外子类也都无法直接访问
  • 私有属性和私有方法仅仅用于做内部的事情
  • 可以在子类中使用父类公有方法间接的访问父类的私有属性或者私有方法

多继承

在python中,子类可以拥有多个父类,并具有所有父类属性方法,如果方法名重复,则以第一个出现的父类为准,所以要尽量避免在多个方法名重复的时候使用多继承

class 类名(父类1, 父类2, ..., 父类n):
    语句

多态

多态是不同的子类对象调用相同的父类方法产生不同的执行效果

  • 多态可以增加代码的灵活度
  • 继承重写父类方法为前提
  • 是调用方法的技巧,不会影响类的内部设计

总结

  • 通常把创建出来的对象称为实例
  • 创建对象动作称为实例化
  • 对象的属性称为实例属性
  • 对象调用的方法称为实例方法
  • 类是一个特殊的对象,python中一切都是对象

类属性和实例属性

类属性就是实例属性

  • 类属性是给类对象中定义的属性
  • 通常用来定义与这个类相关的特征
  • 类属性不会用于记录具体对象的特征
class tool:
    count = 0

    def __init__(self):
        tool.count += 1

    def __str__(self):
        return str(tool.count)


a = tool()
a = tool()
a = tool()
a = tool()
a = tool()
b = tool()
print(tool)
# 输出结果为6,因为每次结果都加在了类名访问的属性上了,可以使用类名.属性进行访问其中的值

如果使用对象名获取类属性值不会出错,如果使用对象名对类属性值进行修改时会出现错误

类方法和静态方法

类变量:类和类的实例都可以访问类变量,但只有类可以修改类变量

如果使用类的实例来修改类变量,那么python会自动给生成一个与类变量同名的成员变量,之后所有通过类的实例来访问和修改类变量,实际上访问和修改的是同名的成员变量。

####类方法

  • 类属性就是针对类对象定义的属性
  • 类属性用于定义与这个类有关的特征
  • 类方法就是针对类对象定义的类方法
语法
@classmethod #单词意思为类方法
def 类方法名(cls):# cls为class的缩写
    pass
  • 类方法需要使用修饰器@classmethod进行标识,告诉编译器这是一个类方法

  • 类方法的第一个参数是cls

    • 由哪个类调用的该方法,cls就是哪个类
    • cls与实例对象的self作用类似
    • 也可以不使用cls命名,改成其他也可以
  • 在方法内部可以通过cls.访问类的属性以及调用类的方法

静态方法

如果一个方法既不需要访问实例属性或者调用实例方法,也不需要访问类属性或者类方法,此时可以将其定义为静态方法

method 方法,ˈmeTHəd

例如

class Dog:
    def run():
        print("狗在跑")

run()方法没有访问实例属性或者调用实例方法,只有一个输出语句,此时的run()方法为静态方法

语法

定义为静态方法后,无需传递self参数

@staticmethod
def 方法名():
    pass
class Dog:

    def __init__(self, name):
        self.name = name

    @staticmethod
    def test():
        print("测试")


dog = Dog("狗")
dog.test()
Dog.test()

调用:对象.方法名()或者类名.方法名()

调用时与普通的方法几乎没有区别,唯一的区别就在于可以使用类名.方法名()进行调用

单例

单例设计模式

设计模式:前人工作的总结和提炼,通常时针对某一问题的成熟的解决方案

单例设计模式:目的是让类创建的对象在系统中只有唯一的一个实例,每一次执行类名()返回的对象内存地址都是相同的

__new__()方法

当使用类名()创建对象时,python解释器会调用__new__()方法为对象分配内存空间

__new__()方法:

  • 为对象分配内存空间
  • 返回对象的引用

文件

文件分为文本文件和二进制文件

打开使用open(路径字符串, 操作模式, encoding=None)函数,如果指定文件存在,返回文件操作对象,如果不存在,抛出异常,文件名区分大小写

文件操作模式

其后跟着b代表处理二进制文件,如rb,wb,ab

模式含义
r只读,为默认方式,如果文件不存在,则抛出异常
w只写方式打开,如果文件存在会被覆盖掉,如果不存在,创建新文件
a追加的方式打开,如果文件存在,指针移动到末尾,如果不存在,创建新文件
r+读写的方式打开,文件指针放在开头(可以实现在开头追加内容),如果文件不存在,则抛出异常
w+读写方式打开,如果文件存在会被覆盖掉,如果不存在,创建新文件
a+读写的方式打开,如果文件存在,指针移动到末尾,如果不存在,创建新文件

频繁进行读写的方式打开会影响文件读写效率,更推荐使用只读、只写方式进行访问

####操作方法

方法名含义
f.read()读取文件到内存
f.write(字符串)将指定内容写入到文件
f.close()关闭文件
f.readline()按行读取,用于大文件的读取

文件指针

  • 标记文件从哪个位置进行读取
  • 第一次打开时,文件指针通常指向第一个位置
  • 执行read()方法后,文件指针会移动到读取内容的末尾,执行read()方法后,不能再继续进行获取内容,因为文件指针移动到了末尾

按行读取

读取后自动移动至下一行

file = open("D:\\VM\\1.txt", "r", encoding="UTF-8")
while True:
    text = file.readline()

    if not text:# 内容为空
        break
    print(text)
file.close()

文件按行复制

file = open("D:\\VM\\1.txt", "r", encoding="UTF-8")
file2 = open("D:\\VM\\2.txt", "a", encoding="UTF-8")
while True:
    text = file.readline()
    if not text:
        break
    print(text, end="")
    file2.write(text)

file.close()
file2.close()

OS模块

可以实现文件的创建、重命名、删除等在文件资源管理器进行的操作

正则表达式regex

ˈreɡeks正则表达式

在一堆文本中提取特定的字符

####普通字符

普通字符可以直接匹配,直接输入相关字符即可

元字符

还有一些特殊字符,不能直接匹配它们,是有特殊含义的,这些被称为元字符

. * + ? \ [ ] ^ $ { } | ( )
  • .表示匹配除换行符之外的任意单个字符

    这是红色
    这是绿色
    这是蓝色
    这是紫色
    

    在此段文字中,若要匹配所有的颜色,可以使用.色进行匹配,即查找以结尾的包含前一个字符的串

    结果为

    红色
    绿色
    蓝色
    紫色
    
  • *表示匹配前面的子表达式任意次数,包含0次,即匹配可以与子表达式中前边的相符合的子串部分,以及全部匹配后,连续的子表达式最后一个字符

  • image-20210528090043460

    格式子表达式 *

    这是,红色233333
    这是,绿色333
    这是,蓝色3
    这是,紫色
    

    匹配所有的3可以写为3 *

    结果为

    33333
    333
    3
    

    匹配所有的后的内容,.*含义为匹配包含,后的任意的字符

    结果为

    红色233333
    绿色333
    蓝色3
    紫色
    
    这是,红色色色色色色
    这是,绿色色色色色色色色色色色
    这是,蓝色3
    这是,紫色
    

    如果想匹配以绿开头,以色结尾后的任意字符可以写为绿色*

    结果为

    绿色色色色色色色色色色色
    
  • +代表匹配前面的表达式一次或者多次,不包括0次,即要匹配完全和子表达式相同的串,以及全部匹配后,连续的子表达式最后一个字符

    这是,红色色色色色色
    这是,绿色色色色色色色色色色色
    这是,绿色
    这是,绿
    这是,紫色
    

    绿色+匹配结果为

    绿色色色色色色色色色色色
    绿色
    
  • { }指定匹配次数

    格式子串{最少次数,最多次数},如果省略最多次数,则代表匹配含有次数个的子串,其中,后不能加空格

  • ?代表非贪婪模式

  • \代表对元字符进行转义

    这是.红色色色色色色
    这是.绿色色色色色色色色色色色
    这是.绿色
    这是.绿
    这是.紫色
    

    所想匹配所有的.可以使用\.进行匹配

    若想匹配.以及其前边的所有字符,可以使用.*\.进行匹配,结果为

    这是.
    这是.
    这是.
    这是.
    这是.
    
    其他字符含义
    \d\D匹配或者不匹配所有的数字
    \s\S匹配或者不匹配所有的空白字符,包含tab 空格 换行符
    \w\W匹配或者不匹配所有的文字字符,字母、数字、下划线组成,文字字符包含Unicode中的字符,例如 汉字等,可以通过更改编码方式进行匹配
  • [ ]匹配几个字符之一

    方括号内允许出现其他的表达式,方括号内除了[ ]之外的其他元字符都失去了原有的作用

    如果在方括号内使用^,代表非的概念,即不包含这些字符的所有内容

    格式

    • [范围-范围]

      代表匹配范围内的所有字符

    • ``````[字符1....字符n]```

      只匹配其中出现的字符

    这是.红色色色色色色
    这是.绿色色色色色色色色色色色
    这是.绿色
    这是.绿
    这是.紫色
    

    只匹配绿色和紫色[绿紫]色结果为

    绿色
    绿色
    紫色
    

####贪婪模式和非贪婪模式

之前用到的+ * ?在一行中都是贪婪模式,使用时,尽可能匹配多的内容

例如

<head>
    <p>走走走</p>
</head>

想要匹配HTML标签,使用<.*>匹配时,匹配结果为

<head>
    <p>走走走</p>
</head>

由此可见,将走走走也匹配进去了

可以通过添加?使用非贪婪模式

使用<.*?>匹配结果为

<head>
    <p></p>
</head>

9

Q.E.D.


念念不忘,必有回响。