【python】 程序设计基础

总结

python 默认变量都是字符串

配置

数据源

C:\Users\Jarvis\AppData\Roaming\pip -> pip.ini
Jarvis是用户名

阿里云数据源不如清华源

[global]
timeout = 10000
index-url = https://pypi.tuna.tsinghua.edu.cn/simple

临时使用:
可以在使用pip的时候在后面加上-i参数,指定pip源
pip install scrapy -i https://pypi.tuna.tsinghua.edu.cn/simple

数据类型

表2-4 Python的标量

数值类型

Python的主要数值类型是intfloatint可以存储任意大的数

In [48]: ival = 17239871

In [49]: ival ** 6
Out[49]: 26254519291092456596965462913230729701102721

浮点数使用Python的float类型。每个数都是双精度(64位)的值。也可以用科学计数法表示:

In [50]: fval = 7.243

In [51]: fval2 = 6.78e-5

不能得到整数的除法会得到浮点数

In [52]: 3 / 2
Out[52]: 1.5

要获得C-风格的整除(去掉小数部分),可以使用底除运算符//:

In [53]: 3 // 2
Out[53]: 1

序列函数

enumerate

迭代一个序列时,你可能想跟踪当前项的序号。手动的方法可能是下面这样:

i = 0
for value in collection:
   # do something with value
   i += 1

因为这么做很常见,Python内建了一个enumerate函数,可以返回(i, value)元组序列:

for i, value in enumerate(collection):
   # do something with value

当你索引数据时,使用enumerate的一个好方法是计算序列(唯一的)dict映射到位置的值:

In [83]: some_list = ['foo', 'bar', 'baz']

In [84]: mapping = {}

In [85]: for i, v in enumerate(some_list):
   ....:     mapping[v] = i

In [86]: mapping
Out[86]: {'bar': 1, 'baz': 2, 'foo': 0}

sorted函数

sorted函数可以从任意序列的元素返回一个新的排好序的列表

In [87]: sorted([7, 1, 2, 6, 0, 3, 2])
Out[87]: [0, 1, 2, 2, 3, 6, 7]

In [88]: sorted('horse race')
Out[88]: [' ', 'a', 'c', 'e', 'e', 'h', 'o', 'r', 'r', 's']

sorted函数可以接受和sort相同的参数。

zip函数

zip可以将多个列表、元组或其它序列成对组合成一个元组列表

In [89]: seq1 = ['foo', 'bar', 'baz']

In [90]: seq2 = ['one', 'two', 'three']

In [91]: zipped = zip(seq1, seq2)

In [92]: list(zipped)
Out[92]: [('foo', 'one'), ('bar', 'two'), ('baz', 'three')]

zip可以处理任意多的序列,元素的个数取决于最短的序列

In [93]: seq3 = [False, True]

In [94]: list(zip(seq1, seq2, seq3))
Out[94]: [('foo', 'one', False), ('bar', 'two', True)]

zip的常见用法之一是同时迭代多个序列,可能结合enumerate使用:

In [95]: for i, (a, b) in enumerate(zip(seq1, seq2)):
   ....:     print('{0}: {1}, {2}'.format(i, a, b))
   ....:
0: foo, one
1: bar, two
2: baz, three

给出一个“被压缩的”序列,zip可以被用来解压序列。也可以当作把行的列表转换为列的列表。这个方法看起来有点神奇:

In [96]: pitchers = [('Nolan', 'Ryan'), ('Roger', 'Clemens'),
   ....:             ('Schilling', 'Curt')]

In [97]: first_names, last_names = zip(*pitchers)

In [98]: first_names
Out[98]: ('Nolan', 'Roger', 'Schilling')

In [99]: last_names
Out[99]: ('Ryan', 'Clemens', 'Curt')

reversed函数

reversed可以从后向前迭代一个序列:

In [100]: list(reversed(range(10)))
Out[100]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

要记住reversed是一个生成器(后面详细介绍),只有实体化(即列表或for循环)之后才能创建翻转的序列。

输入

【参考:python技巧2:用input同时输入多个数_graysu的博客-CSDN博客

a,b =input('输入a,b空格隔开:').split()
#此时a,b为str型

a,b =map(int,input('输入a,b空格隔开:').split())
#此时a,b为int型

多行字符串格式化输出

【参考:textwrap — Text wrapping and filling — Python 3.11.0 documentation

import textwrap

# \ 是格式化换行
# 缩进要一致
str1 = """\
    name:{},
    sex:{},
    age:{},
""".format('Jack', 18,'man' )

print(textwrap.dedent(str1)) # 删除文本中每一行中任何常见的前导空格。
"""
name:Jack,
sex:18,
age:man,
"""

错误例子

 """\
name:{},
	sex:{},
    age:{}
"""

"""\
    name:{},
sex:{},
    age:{}
"""

输出

In [74]: template = '{0:.2f} {1:s} are worth US${2:d}'

在这个字符串中,

  • {0:.2f}表示格式化第一个参数为带有两位小数的浮点数。
  • {1:s}表示格式化第二个参数为字符串。
  • {2:d}表示格式化第三个参数为一个整数。

要替换参数为这些格式化的参数,我们传递format方法一个序列:

In [75]: template.format(4.5560, 'Argentine Pesos', 1)
Out[75]: '4.56 Argentine Pesos are worth US$1'

【参考:Python输出函数print总结(python print())_THEAQING-CSDN博客

print(*objects, sep=' ', end='\n', file=sys.stdout)

参数的具体含义如下:

objects --表示输出的对象。输出多个对象时,需要用 , (逗号)分隔。

sep -- 用来间隔多个对象。

end -- 用来设定以什么结尾。默认值是换行符 \n,我们可以换成其他字符。

file -- 要写入的文件对象。

【参考:python - 输入输出 之 字符串前缀u、r、b、f含义_开码河粉-CSDN博客

r:转义无效符
在字符串前加r使当前字符串的转义字符无效,按原样输出


print(u"江西") # 江西

print(r'\n hello \v') # \n hello \v
# 字符串变量
s='\n hello \v'
print(repr(s))# \n hello \v

s=r"123\n123\n"
print(s)
print(type(s))
print(repr(s))
print(type(repr(s)))

'''
123\n123\n
<class 'str'>
'123\\n123\\n'
<class 'str'>
'''


# Python3.6新加特性
account='myaijarvis'
month=12
print(f'我的微信公众号是:{account},已经连续发文{int(month) * 5}天啦!')
# 我的微信公众号是:myaijarvis,已经连续发文60天啦!

【参考:Python repr函数_全村的希望的博客-CSDN博客


python 数值类型只有 int(整形)、float(浮点型,3.x提供17位有效小数,相当于C语言的double)、complex(复数型)

r = (85-72) / 72  *100
print(r)
print('%.1f%%'%r) # %% -> %
print(f'{r:.1f}%') # f'{变量:格式说明符}'
print('{0:.1f}%'.format(r))

print(1/3)
18.055555555555554
18.1%
18.1%
18.1%
0.3333333333333333

复合数据类型

list

list是一种有序的集合

arr=[]
arr.append(1)
arr.append(2)
arr.append(3)
arr.append(4)
for i in range(0,len(arr)):
    print(arr[i],end=' ')#  1 2 3 4
print()

arr.pop() # 删除4
arr.pop(1) # 删除下标为1的数,即数字2
arr.insert(0, 5) # 在下标为0的位置插入5

for a in arr:
    print(a,end=' ')# 5 1 3

tuple

tuple和list非常类似,但是tuple一旦初始化就不能修改

t=() # 空元组
t=(1,) # 一个元素的元组

dict

【参考:使用dict和set - 廖雪峰的官方网站
dict的key必须是不可变对象

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

print(d['Michael']) # 95
print(d.get('Bob')) # 75
print(d.get('Jack')) # None
print(d.get('Jack',-1)) # 设置默认值-1

d.setdefault('Tom',100) # 添加元素

d.pop('Tracy') # 删除元素

for k,v in d.items():
    print(k,v)
    
for i in d:
    print("%s:%s"%(i,d[i]))
    
'''    
Michael 95
Bob 75
Tom 100
'''

请务必注意,dict内部存放的顺序和key放入的顺序是没有关系的。

和list比较,dict有以下几个特点:

  • 查找和插入的速度极快(哈希算法),不会随着key的增加而变慢;
  • 需要占用大量的内存,内存浪费多。

而list相反:

  • 查找和插入的时间随着元素的增加而增加;
  • 占用空间小,浪费内存很少。
    所以,dict是用空间来换取时间的一种方法。

set

s = {'Michael' ,'Bob','Tracy'}

s.add('Jack') # 添加

s.remove('Tracy') # 删除

for k in s:
    print(k)
'''
Michael
Jack
Bob
'''
s_null=set() # 空集合

print(len(s_null)) # 0

数字

在这里插入图片描述

bool

    	False   	True
int 	00
float	0.00.0
str		'' 空字符串	非空字符串

列表	[] 空列表
元组	() 
字典	{}

在这里插入图片描述

日期和时间

Python内建的datetime模块提供了datetimedatetime类型。datetime类型结合了datetime,是最常使用的:

In [102]: from datetime import datetime, date, time

In [103]: dt = datetime(2011, 10, 29, 20, 30, 21)

In [104]: dt.day
Out[104]: 29

In [105]: dt.minute
Out[105]: 30

根据datetime实例,你可以用datetime提取出各自的对象:

In [106]: dt.date()
Out[106]: datetime.date(2011, 10, 29)

In [107]: dt.time()
Out[107]: datetime.time(20, 30, 21)

strftime方法可以将datetime格式化为字符串:

In [108]: dt.strftime('%m/%d/%Y %H:%M')
Out[108]: '10/29/2011 20:30'

strptime可以将字符串转换成datetime对象:

In [109]: datetime.strptime('20091031', '%Y%m%d')
Out[109]: datetime.datetime(2009, 10, 31, 0, 0)

表2-5列出了所有的格式化命令。

表2-5 Datetime格式化指令(与ISO C89兼容)

当你聚类或对时间序列进行分组,替换datetimes的time字段有时会很有用。例如,用0替换分和秒:

In [110]: dt.replace(minute=0, second=0)
Out[110]: datetime.datetime(2011, 10, 29, 20, 0)

因为datetime.datetime是不可变类型,上面的方法会产生新的对象。

两个datetime对象的差会产生一个datetime.timedelta类型:

In [111]: dt2 = datetime(2011, 11, 15, 22, 30)

In [112]: delta = dt2 - dt

In [113]: delta
Out[113]: datetime.timedelta(17, 7179)

In [114]: type(delta)
Out[114]: datetime.timedelta

结果timedelta(17, 7179)指明了timedelta将17天、7179秒的编码方式。

timedelta添加到datetime,会产生一个新的偏移datetime

In [115]: dt
Out[115]: datetime.datetime(2011, 10, 29, 20, 30, 21)

In [116]: dt + delta
Out[116]: datetime.datetime(2011, 11, 15, 22, 30)

高级特性 ***

切片

Python中符合序列的有序序列都支持切片(slice),例如列表,字符串,元组
格式:[start:end:step]
start:起始索引,从0开始,-1表示结束
end:结束索引
step:步长,end-start,步长为正时,从左向右取值步长为负时,反向取值
注意切片的结果不包含结束索引,即不包含最后的一位,-1代表列表的最后一个位置索引

【参考:切片 - 廖雪峰的官方网站

L = list(range(100))
print(L) # 1,2,3,....,99
print(L[-1]) # 99 倒数第一个元素的索引是-1
print(L[:5]) # [0, 1, 2, 3, 4] 前5个
print(L[-5:]) # [95, 96, 97, 98, 99] 后5个

# 只写[:]就可以原样复制一个list
L2=L[:] # 深复制
print(L2) 

# tuple也是一种list,唯一区别是tuple不可变。因此,tuple也可以用切片操作,只是操作的结果仍是tuple:
t=(0, 1, 2, 3, 4, 5)
print(t[:3]) # (0, 1, 2)

# 字符串'xxx'也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串
s='ABCDEFG'
print(s[:3]) # 'ABC'

反向 ***

[i:j:k] 其中k<0

=> [n+i:n+j:k] 默认[-1:-n-1:k]
比如[0:n:1] 中间的为0+n=n ; [-1:-n-1:k] 中间的为 -1 + -n = -n-1
最右边编号为-1,索引范围为-n到-1 ,-n即第一个

a='123456'
print(a[::-1]) 
# 默认 print(a[-1:-len(a)-1:-1]) # 默认 -len(a)-1=-7 相当于字符1的前面一个 -6指向字符1

print(a[0::-1])
print(a[1::-1])
print(a[2::-1]) # 从下标为2的元素翻转读取

654321
654321
1
21
321

下面好像有点错误 以后再说

s='Hello World!'
s[-1:-5:-1] # !dlr
a=[1,2,3,4,5,6]

b1=a[:] #省略全部,代表截取全部内容,可以用来将一个列表拷给另一个列表(深拷贝)
print(b1)
结果:[1, 2, 3, 4, 5, 6]

b=a[0:-1:1] #从位置0开始到结束,每次增加1,截取。不包含结束索引位置,-1代表最后一个位置
print(b)
结果:[1, 2, 3, 4, 5]

==================
[:end]
c1=a[:3] #省略起始位置的索引,以及步长。默认起始位置从头开始,默认步长为1,结束位置索引为3
print(c1)
结果:[1, 2, 3]
==================

c=a[0:5:3] #从第一个位置到第6个位置,每3个取一个值
print(c)
结果:[1, 4]

d=a[5:0:-1] #反向取值
print(d)
结果:[6, 5, 4, 3, 2]

d1=a[::-1]
print(d1)
结果:[6, 5, 4, 3, 2, 1]

迭代

【参考:迭代 - 廖雪峰的官方网站

如何判断一个对象是可迭代对象呢?方法是通过collections.abc模块的Iterable类型判断:

from collections.abc import Iterable

print(isinstance('abc', Iterable))  # str是否可迭代
# True
print(isinstance([1, 2, 3], Iterable))  # list是否可迭代
# True
print(isinstance(123, Iterable))  # 整数是否可迭代
# False

对list实现类似Java那样的下标循环怎么办?Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身:

for i, value in enumerate(['A', 'B', 'C']):
    print(i, value)

0 A
1 B
2 C
for x, y in [(1, 1), (2, 4), (3, 9)]:
	print(x, y)

1 1
2 4
3 9

列表生成式

【参考:列表生成式 - 廖雪峰的官方网站

[x * x for x in range(1, 11)]
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

[x * x for x in range(1, 11) if x % 2 == 0]
# [4, 16, 36, 64, 100]

# 全排列
[m + n for m in 'ABC' for n in 'XYZ']
# ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

import os # 导入os模块,模块的概念后面讲到
[d for d in os.listdir('.')] # os.listdir可以列出文件和目录

if … else

在一个列表生成式中,for前面的if … else是表达式,而for后面的if是过滤条件,不能带else

[x for x in range(1, 11) if x % 2 == 0]
# [2, 4, 6, 8, 10]

[x if x % 2 == 0 else -x for x in range(1, 11)]
# [-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]

生成器

【参考:生成器 - 廖雪峰的官方网站
一边循环一边计算的机制,称为生成器:generator

其创建方式为,把列表推导式两端的方括号改成圆括号

g = (x * x for x in range(10))  # 注意,这里是圆括号
print(g)  # <generator object <genexpr> at 0x000001E584F361B0> generator也是可迭代对象

print(next(g))  # 每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素

for n in g:
    print(n)

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n = n + 1
    return 'done'

'''
t = (b, a + b) # t是一个tuple
a = t[0]
b = t[1]
'''

如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator函数,调用一个generator函数将返回一个generator:

调用generator函数会创建一个generator对象,多次调用generator函数会创建多个相互独立的generator

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'
f = fib(6)
f # <generator object fib at 0x104feaaa0>

for n in fib(6):
	print(n)

1
1
2
3
5
8

yield

https://www.cnblogs.com/ellisonzhang/p/10273843.html
简要理解:yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后开始。

迭代器

【参考:迭代器 - 廖雪峰的官方网站
我们已经知道,可以直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如list、tuple、dict、set、str等;

一类是generator,包括生成器和带yield的generator function

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。

可以使用isinstance()判断一个对象是否是Iterable对象:

>>> from collections.abc import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False

而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。

可以使用isinstance()判断一个对象是否是Iterator对象:

>>> from collections.abc import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)

生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。

把list、dict、str等Iterable变成Iterator可以使用iter()函数:

>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

函数式编程

高阶函数

【参考:高阶函数 - 廖雪峰的官方网站

让函数的参数能够接收别的函数

def add(x, y, f):
    return f(x) + f(y)

map

map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回

>>> def f(x):
...     return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]

>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
['1', '2', '3', '4', '5', '6', '7', '8', '9']

reduce

reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:

常常与map一起使用

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

# 求和
>>> from functools import reduce
>>> def add(x, y):
...     return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25

filter

Python内建的filter()函数用于过滤序列。

和map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

def is_odd(n):
    return n % 2 == 1

list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
# 结果: [1, 5, 9, 15]

sorted

>>> sorted([36, 5, -12, 9, -21])
[-21, -12, 5, 9, 36]

>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]

>>> sorted(['bob', 'about', 'Zoo', 'Credit'])
['Credit', 'Zoo', 'about', 'bob']

>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)
['about', 'bob', 'Credit', 'Zoo']
# 分别按名字排序:
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]

def by_name(t):
	return t[0].lower()
L2 = sorted(L, key=by_name)
print(L2)

# 用成绩来进行排序,成绩由高到低

L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]

def by_score(t):
    return t[1] # return -t[1] 下面就不用 reverse

L2 = sorted(L, key=by_score,reverse=True)
print(L2)

返回函数

【参考:返回函数 - 廖雪峰的官方网站

返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

def count():
    fs = []
    for i in range(1, 4):

        def f():
            return i * i

        fs.append(f)
    return fs  # 返回一个列表,里面三个数


f1, f2, f3 = count()  # 列表自动会给三个变量赋值
# 此时就已经运行count()函数了,然后i=3了

print(f1())  # 9
print(f2())  # 9
print(f3())  # 9

如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:

def count():
    def f(j):
        def g():
            return j*j
        return g
    fs = []
    for i in range(1, 4):
        fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
    return fs
再看看结果:

>>> f1, f2, f3 = count()
>>> f1()
1
>>> f2()
4
>>> f3()
9

匿名函数

>>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
[1, 4, 9, 16, 25, 36, 49, 64, 81]

通过对比可以看出,匿名函数lambda x: x * x实际上就是:

def f(x):
    return x * x

匿名函数有个限制,就是只能有一个表达式不用写return,返回值就是该表达式的结果。

匿名函数也是一个函数对象,利用lambda作为返回值时,得到的是一个函数,而不是一个值。

装饰器

【参考:装饰器 - 廖雪峰的官方网站
decorator被称为装饰模式

还不是很理解

偏函数

【参考:偏函数 - 廖雪峰的官方网站


模块

【参考:安装第三方模块 - 廖雪峰的官方网站
模块搜索路径
当我们试图加载一个模块时,Python会在指定的路径下搜索对应的.py文件,如果找不到,就会报错:

>>> import mymodule
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named mymodule

默认情况下,Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys模块的path变量中:

>>> import sys
>>> sys.path
['c:\\Users\\Jarvis\\Desktop\\Code\\py', 
'C:\\anaconda3\\python37.zip',
'C:\\anaconda3\\DLLs', 
'C:\\anaconda3\\lib', 
'C:\\anaconda3', 
'C:\\Users\\Jarvis\\AppData\\Roaming\\Python\\Python37\\site-packages', 
'C:\\anaconda3\\lib\\site-packages', 
'C:\\anaconda3\\lib\\site-packages\\win32', 'C:\\anaconda3\\lib\\site-packages\\win32\\lib', 'C:\\anaconda3\\lib\\site-packages\\Pythonwin']

如果我们要添加自己的搜索目录,有两种方法:

一是直接修改sys.path,添加要搜索的目录:

>>> import sys
>>> sys.path.append('/Users/michael/my_py_scripts')

这种方法是在运行时修改,运行结束后失效

第二种方法是设置环境变量PYTHONPATH,该环境变量的内容会被自动添加到模块搜索路径中。设置方式与设置Path环境变量类似。注意只需要添加你自己的搜索路径,Python自己本身的搜索路径不受影响。

面向对象编程

类和实例

【参考:类和实例 - 廖雪峰的官方网站

class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score

    def get_grade(self):
        if self.score >= 90:
            return 'A'
        elif self.score >= 60:
            return 'B'
        else:
            return 'C'
            
lisa = Student('Lisa', 99)
bart = Student('Bart', 59)
print(lisa.name, lisa.get_grade())
print(bart.name, bart.get_grade())

访问限制

【参考:访问限制 - 廖雪峰的官方网站

继承和多态

【参考:继承和多态 - 廖雪峰的官方网站

当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。

获取对象信息

【参考:获取对象信息 - 廖雪峰的官方网站
基本类型都可以用type()判断:
isinstance()可以告诉我们,一个对象是否是某种类型

如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:

仅仅把属性和方法列出来是不够的,配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态:

>>> hasattr(obj, 'x') # 有属性'x'吗?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有属性'y'吗?
False
>>> setattr(obj, 'y', 19) # 设置一个属性'y'
>>> hasattr(obj, 'y') # 有属性'y'吗?
True
>>> getattr(obj, 'y') # 获取属性'y'
19
>>> obj.y # 获取属性'y'
19

实例属性和类属性

【参考:实例属性和类属性 - 廖雪峰的官方网站

实例属性属于各个实例所有,互不干扰;

类属性属于类所有,所有实例共享一个属性;

给实例绑定属性的方法是通过实例变量,或者通过self变量:

class Student(object):
    def __init__(self, name):
        self.name = name

s = Student('Bob')
s.score = 90
但是,如果Student类本身需要绑定一个属性呢?可以直接在class中定义属性,这种属性是类属性,归Student类所有:

class Student(object):
    name = 'Student'
当我们定义了一个类属性后,这个属性虽然归类所有,但类的所有实例都可以访问到。
>>> class Student(object):
...     name = 'Student'
...
>>> s = Student() # 创建实例s
>>> print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
Student
>>> print(Student.name) # 打印类的name属性
Student
>>> s.name = 'Michael' # 给实例绑定name属性
>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
Michael
>>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问
Student
>>> del s.name # 如果删除实例的name属性
>>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了
Student

在编写程序的时候,千万不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性.

面向对象高级编程 wait

错误、调试和测试

错误处理

【参考:错误处理 - 廖雪峰的官方网站
https://docs.python.org/3/library/exceptions.html#exception-hierarchy

调试

【参考:调试 - 廖雪峰的官方网站

凡是用print()来辅助查看的地方,都可以用断言(assert)来替代:

def foo(s):
    n = int(s)
    assert n != 0, 'n is zero!'
    return 10 / n

def main():
    foo('0')
assert的意思是,表达式n != 0应该是True,否则,根据程序运行的逻辑,后面的代码肯定会出错。

单元测试 wait

【参考:单元测试 - 廖雪峰的官方网站

文档测试 wait

【参考:文档测试 - 廖雪峰的官方网站

IO编程 wait

文件读写

【参考:文件读写 - 廖雪峰的官方网站

with语句来自动帮我们调用close()方法

StringIO和BytesIO

【参考:StringIO和BytesIO - 廖雪峰的官方网站
StringIO顾名思义就是在内存中读写str。
StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO

操作文件和目录

【参考:操作文件和目录 - 廖雪峰的官方网站

序列化

【参考:序列化 - 廖雪峰的官方网站

进程和线程 wait

【参考:进程和线程 - 廖雪峰的官方网站

正则表达式 wait

【参考:正则表达式 - 廖雪峰的官方网站
【参考:正则表达式 - 廖雪峰的官方网站

常用内建模块 wait

【参考:常用内建模块 - 廖雪峰的官方网站

collections ***

常用第三方模块 ***

【参考:常用第三方模块 - 廖雪峰的官方网站

字典(Dictionary)

items()

dict = {'Google': 'www.google.com', 'Runoob': 'www.runoob.com', 'taobao': 'www.taobao.com'}
 
print "字典值 : %s" %  dict.items()
 
# 遍历字典列表
for key,values in  dict.items():
    print key,values

字典值 : [('Google', 'www.google.com'), ('taobao', 'www.taobao.com'), ('Runoob', 'www.runoob.com')]
Google www.google.com
taobao www.taobao.com
Runoob www.runoob.com

字符串

字符串是一个序列的Unicode字符,因此可以像其它序列,比如列表和元组(下一章会详细介绍两者)一样处理:

In [64]: s = 'python'

In [65]: list(s)
Out[65]: ['p', 'y', 't', 'h', 'o', 'n']

join()

'separtor'.join(sequence)

参数说明
separtor:分隔符。可以为空
sequence:要连接的元素序列、字符串、元组、字典
上面的语法即:以separtor作为分隔符,将sequence所有的元素合并成一个新的字符串

返回值:返回一个以分隔符sep连接各个元素后生成的字符串

实例:
seq3 = ('hello','good','boy','doiido')
print(':'.join(seq3)) # hello:good:boy:doiido

data={
    "id":1000,
    "name":"Jack",
    "age":18
}
keys=",".join(data.keys())
print(keys) # id,name,age

文件操作

with open() as f

https://blog.csdn.net/MsSpark/article/details/86745391

with open'filename.txt','r',encode='utf-8') as f:
   data_user=pd.read_csv(f)  #文件的读操作

with open('data.txt','w',encode='utf-8') as f:
   f.write('hello world')  #文件的写操作
  

file对象属性

file.read([size])   将文件数据作为字符串返回,可选参数size控制读取的字节数
file.readlines([size])   返回文件中行内容的列表,size参数可选
file.write(str)   将字符串写入文件
file.writelines(strings)   将字符串序列写入文件
file.close()   关闭文件
file.closed	表示文件已经被关闭,否则为False

file.mode	Access文件打开时使用的访问模式
file.encoding	文件所使用的编码
file.name	文件名
file.newlines	未读取到行分隔符时为None,只有一种行分隔符时为一个字符串,当文件有多种类型的行结束符时,则为一个包含所有当前所遇到的行结束的列表
file.softspace	为0表示在输出一数据后,要加上一个空格符,1表示不加。这个属性一般程序员用不着,由程序内部使用

函数

定义函数

【参考:定义函数 - 廖雪峰的官方网站

如果没有return语句,函数执行完毕后也会返回结果,只是结果为None。return None可以简写为return

数据类型检查可以用内置函数isinstance()实现

def my_abs(x):
    if not isinstance(x, (int,float())):
        raise TypeError('类型有误')
    if x>=0:
        return x;
    elif x<0:
        return -x;
    
print(my_abs(-1)) # 1
print(my_abs('x'))

1
Traceback (most recent call last):
  File "c:\Users\Jarvis\Desktop\Code\py\demo.py", line 10, in <module>
    print(my_abs('x'))
  File "c:\Users\Jarvis\Desktop\Code\py\demo.py", line 2, in my_abs
    if not isinstance(x, (int,float())):
TypeError: isinstance() arg 2 must be a type or tuple of types
import math

def move(x, y, step, angle=0):
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)
    # 在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值
    return nx, ny 

x, y = move(100, 100, 60, math.pi / 6)
print(x, y) # 151.96152422706632 70.0

r = move(100, 100, 60, math.pi / 6)
print(r) # (151.96152422706632, 70.0)

函数的参数

【参考:函数的参数 - 廖雪峰的官方网站

一是必选参数在前,默认参数在后,否则Python的解释器会报错
默认参数必须指向不变对象

也可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上。比如调用enroll(‘Adam’, ‘M’, city=‘Tianjin’),意思是,city参数用传进去的值,其他默认参数继续使用默认值。

def enroll(name, gender, age=6, city='Beijing'):
    print('name:', name)
    print('gender:', gender)
    print('age:', age)
    print('city:', city)
    
    
enroll('Bob', 'M', 7)
enroll('Adam', 'M', city='Tianjin')

可变参数

# 在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple
def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum
    
# 调用该函数时,可以传入任意个参数,包括0个参数
calc() # 0
calc((1,2,3)) # 6

nums = [1, 2, 3]
calc(*nums) # *nums表示把nums这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见

装饰器 待理解

在这里插入图片描述
在这里插入图片描述

call

只要定义类型的时候,实现__call__函数,这个类型就成为可调用的
换句话说,我们可以把这个类型的对象当作函数来使用,相当于 重载了括号运算符

class Person():
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
    def __call__(self, friend):
        print('My name is %s...' % self.name)
        print('My friend is %s...' % friend)

B = Person('Jack','male')
B('Mark')

output:
My name is Jack
My friend is Mark

1.from 包名 import 函数名

from datatime import datatime
datetime.now()



2.import 函数名

import datetime
datetime.datetime.now() 

在这里插入图片描述

OS

在这里插入图片描述
在这里插入图片描述

path

在这里插入图片描述
在这里插入图片描述

system

在这里插入图片描述
在这里插入图片描述

数据库操作

MySQL

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第1~3章主要介绍Python基本概述与基础编程方面的内容,包括Python基本介绍、Python开发环境搭建、Python基础语法、数据类型与运算符方面的内容。   第4章主要介绍Python的几种典型控制结构,事实上,控制结构在编程中非常重要,对于这一部分内容建议重点掌握,要求掌握得非常熟练,尤其是循环结构部分。   第5章和第6章主要介绍Python中稍微复杂一些的基础知识,包括迭代与生成、函数、模块等基础知识。   第7章和第8章主要介绍Python面向对象编程方面的知识,对于这一部分的知识尽量用了比较通俗的案例进行讲解,希望大家可以更好地掌握,因为后续如果想做一些大型的项目,常常会用面向对象的编程思想去编程。   第9~12章主要介绍Python基础中的一些提升部分的知识,主要包括正则表达式、数据库操作、文件操作、异常处理等,这一部分的知识事实上我们在实际项目中会常常遇到,用得非常多,是基础提升的关键部分。   第13章主要为大家介绍一个火车票查询与自动订票的项目,主要目的是希望读者可以运用之前学过的基础知识完成这个项目,将基础知识运用于项目开发实践。   第14章主要介绍了一个2048小游戏项目,主要目的是希望读者可以通过此2048小游戏项目,熟练掌握Python基础知识,将Python基础知识融会贯通,并完成一个好玩的小游戏项目,培养综合运用知识的能力。   通过这14章的学习,目的是希望读者可以对Python基础有一个全面的掌握,同时,书中涉及的代码,希望读者可以自己手动输入一遍,这样可以更好地掌握相关知识。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值