forked from Jaanai-Lu/Statistics
-
Notifications
You must be signed in to change notification settings - Fork 0
/
000.2 Python基础(N)
623 lines (442 loc) · 21 KB
/
000.2 Python基础(N)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
"""
两周学习python
作者:陆震
日期:17/05/2019
"""
def main():
pass
for i in range(3):
print(i)
print('-' * 10)
# 使用斜杠(\)将过长的一行代码分割成多行
print('Life is short,\
I use python')
# 点对多点的赋值:将一个数据在一次赋值操作中同时传递给多个变量
a = b = c = 2
print(a, b, c)
# 多点对多点的赋值:在一条语句中将多个数据赋值给多个变量,个数和位置要分别一一对应
a, b, c = 'Jaanai', 'Zhen', 'Lu'
print(a)
print(b)
print(c)
# 浮点数打印输出时默认保留一位小数,另外可以自定义输出精度
d = 25.30
print(d)
# 使用 '%f' 定义输出精度保留6位小数
print('%f' % d)
# '%.2f' 保留2位小数
print('%.2f' % d)
# 若数字位于点号前,则表示保留到小数点前的位数
print('%1.f' % d)
# 字符串索引
print(a)
print(a[-3:])
# 列表即 方括号[] ,可以实现多种数据类型的嵌套,甚至可以实现在列表中嵌套列表
list1 = ['hi', 20, 3.14]
list2 = ['Jaanai', 22]
print(list1)
print(list1[0])
print(list1[1:])
print(list1 + list2)
# 可对列表中的元素进行更新,即重新赋值
list1[0] = 'hello'
print(list1)
# 元组即 圆括号() ,元组内的元素不能被重新赋值,其内部元素是固定的,所以也被称为只读型列表
tuple1 = ('hi', 20, 3.14)
tuple2 = ('Jaanai', 22)
print(tuple1)
print(tuple1[0])
print(tuple1[1:])
print(tuple1 + tuple2)
# 字典即 大括号{} ,相比于前俩种,操作更加灵活和复杂
# 其中一个区别就是列表和元组是有序的元素集合,字典却是一组无序的元素集合
# 虽然字典是无序的,但是为了达到对字典内元素的可操控性,对于内部的每个元素都会加入相应的键值
# 若需要对字典中元素的值进行赋值或重新赋值等,只能通过元素对应的键值进行,而不能使用在列表和元组中操作索引值的方法
dict_1 = {}
dict_1['one'] = 'This is one'
dict_1[2] = 'This is two'
dict_info = {'name': 'Zhen', 'num': 3.14, 'city': 'Harbin'}
print(dict_1) # 输出整个dict_1字典
print(dict_1.keys()) # 输出dict_1的所有键值
print(dict_info.keys())
print(dict_info.values()) # 输出所有值
print(dict_info['name']) # 输出键值为name的值
print(dict_1[2])
# 取模运算符即 % ,符号前的变量以符号后的变量为模进行取模运算
# 求幂运算符即 ** ,符号前的变量以符号后的变量为幂进行求幂运算
# 取整运算符即 // ,符号前的变量以符号后的变量为底进行取整运算
a = 7
b = 3
a //= b
print('a // b =', a)
a = 7 # 对a进行重置
a %= b
print('a % b = ', a)
# 比较运算分为单层比较和多层比较
# 单层比较指参与比较运算的变量只是前后俩个变量
#多层比较指参与比较运算的变量可以有3个及以上
a = 5
b = 4
c = 2
print(a == b == c) # 判断a是否等于b且b是否等于c
print(a > b > c) # 判断a是否大于b且b是否大于c
print(a < b < c) # 判断a是否小于b且b是否小于c
# 布尔运算符,常见的即 and与、or或、not非 ,且这三个布尔运算符在运算后返回的运算结果值也是布尔性的
a = 5
b = 4
c = 2
print(a>b and a<b)
print(not a<b)
# 成员运算符,最典型的是 in
# 若我们已经拥有一个目标列表,当想判断某个元素是否是目标列表中的元素时,可以使用成员运算符确定,使用成员运算符返回的值是布尔型的
list1 = ['hi', 20, 3.14]
a = 3.154
b = 'hi'
print(a in list1)
print(b in list1)
# 身份运算符,用于判断所比较的变量是否是同一个对象,或者定义的这些变量是否指向相同的内存地址
# 返回的值是布尔型的
# 常用的身份运算符是 is, is not
a = 500
b = 500
print('a的内存地址:', id(a)) # id()用于返回所定义变量的内存地址
print('b的内存地址:', id(b))
print('a is not b', a is not b)
print('a == b', a == b)
print('a is b', a is b)
# 注意: is 和 等于运算符== 有着本质的区别,后者仅仅比较变量值是否相等,前者比较变量是否属于同一个对象,因为有时候相同的数值却有不同的内存地址
# 循环语句:while循环,for循环
# 循环判断语句:break、cotinue、pass
# break:出现在循环代码块中,用于中断当次循环并结束整个循环语句
# 在break循环控制语句触发后,整个循环语句就直接结束
num = 10
for i in range(10):
if i == 5:
break
if i < num:
print('the num is', i)
# continue:出现在循环代码块中,用于中断当次循环并直接开始下次循环
# 在continue循环控制语句触发后,受影响的仅仅是当次循环,之后的循环过程不受任何影响
num = 10
for i in range(10):
if i == 5:
continue
if i < num:
print('the num is', i)
# pass:出现在循环代码块中,不做任何操作,继续执行当次循环中的后续代码,主要用于保持代码块的完整性
# 不执行任何操作,循环不卡壳,继续执行下去
num = 10
for i in range(10):
if i == 5:
pass
if i < num:
print('the num is', i)
# 有个非常实用的操作,可以通过实用循环完成对列表的迭代,通过对列表的迭代可以遍历整个列表中的所有元素
list1 = ['hi', 20, 3.14]
for i in list1:
print(i)
# 函数:一组按照相应的规则编写的能够实现相关功能的代码块
# 通过对函数的使用,代码具备了模块化的性质,降低了代码编写的重复性
def function():
print('Jaanai')
# 若在return后无任何内容或在代码段中没有使用return关键词,那么函数默认返回一个空值 None 给调用该函数的方法
return
a = function()
print(a)
# 虽然函数被定义成可传递参数的函数,但可以不传递参数给这个函数
# 在不传递参数给该函数时,函数会使用函数定义的默认参数
# 若是调用函数时传递了合法的参数,该函数就会使用传递的参数进行相应的操作,而不再使用默认参数
def function(str = 'hi'):
print('What you say is:', str)
function('hello')
# 在自定义附带参数的函数时,会涉及参数的传递方式,参数的传递方式有与定义的参数类别有非常大的联系,经常会用到的几种参数类别有:
# 1. 必备参数:调用该函数时必须传递相应参数,否则程序会报错
def funtion1(str): # 必备参数
print('What you say is:', str)
return
funtion1('hello')
# 2. 关键字参数:使用关键字参数来确定传入的参数值,在传递时调换关键字的位置不会对最终的参数传递顺序产生影响
def function2(str2 = 'luzhen', str1 = 'Jaanai'): # 关键字参数
print('What you say is:', str1, str2)
return
function2()
# 3. 默认参数:没有传递参数时,使用默认参数
def function3(str = 'luzhen'): # 默认参数
print('What you say is:', str)
return
function3()
# 4. 不定长参数:当需要传递给函数的参数比函数声明时的参数要多很多时,可以使用不定长参数来完成
def function4(arg1, *arg2): # 不定长参数
print(arg1)
for i in arg2:
print(i)
return
function4(10, 1, 2, 3, 4, 5)
# Python中的类:
# Python是面向对象的程序语言,所以也有面向对象的方法
# 在Python中创建一个类或对象不是一件困难的事
# 类是用来描述具有相同属性和方法的对象的集合,定义了该集合中每个对象所共有的属性和方法,对象则是类的实例
# 类的创建:
# 使用 class 关键词来创建一个类,在class关键词之后紧跟类的名称,以冒号 :结尾
# 注意:
# 1. 类变量:在创建的类中会定义一些变量,这些变量叫做类变量,
# 类变量的值在这个类的所有实例之间是共享的,同时内部类或者外部类也能对这个变量的值进行访问
# 2. __init__():是类的初始化方法,我们在创建一个类的实例时就会调用一次这个方法
# 3. self:代表类的实例,在定义类的方法时是必须要有的,但是在调用时不必传入参数
class Student:
student_Count = 0
def __init__(self, name, age):
self.name = name
self.age = age
Student.student_Count += 1
def dis_student(self):
print('Student name:', self.name,\
'Student age:', self.age)
student1 = Student('Tang', '20') # 创建第1个Student对象
student2 = Student('Lu', '25') # 创建第2个Student对象
student1.dis_student()
student2.dis_student()
print('Total Student:', Student.student_Count)
# 类的继承:
# 定义一个类,通过继承获得另一个类的所有方法,被继承的类叫做父类,进行继承的类叫做子类
# 这样可以有效解决代码的重用问题,可提升代码效率和利用率,还可增加可扩展性
# 注意:
# 当一个类被继承时,这个类中的类初始化方法是不会被自动调用的,
# 所以我们使用Python代码去调用某个方法时,默认会现在所在的类中进行查找,
# 如果没有找到,则判断所在的类是否为子类,若为子类,就继续到父类中查找
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def dis_name(self):
print('name is:', self.name)
def set_age(self, age):
self.age = age
def dis_age(self):
print('age is:', self.age)
class Student(People):
def __init__(self, name, age, school_name):
self.name = name
self.age = age
self.school_name = school_name
def dis_student(self):
print('School name is:', self.school_name)
student = Student('Nie', '26', 'GLDZ') # 创建一个Student对象
student.dis_student() # 调用子类的额方法
student.dis_name() # 调用父类的方法
student.dis_age() # 调用父类的方法
student.set_age(22) # 调用父类的方法
student.dis_age() # 调用父类的方法
# 类的重写:
# 在继承一个类之后,父类中的很多方法也许就不能满足我们现有的需求了
# 这时我们需要对类进行重写
class Parent: # 定义父类
def __init__(self):
pass
def print_info(self):
print('This is Parent.')
class Child(Parent): # 定义子类
def __init__(self):
pass
def print_info(self): # 对父类的方法进行重写
print('This is Child.')
child = Child()
child.print_info()
if __name__ == '__main__':
main()
有10个问题:
1. Python中都是对象吗?
字符串是对象。列表对象,函数对象,甚至模块也是对象。
任何东西都是一个对象,因为它可以赋值给一个变量或作为参数传递给一个函数。
任何可以(合法地)放在等号右边的东西都是(或创建)Python中的对象。
def hello():
print("say hello")
hi = hello()
hi()
hello()
对象:1、ID 2、值(可变的或不可变的)
可变的:当更改项目时,ID仍然是相同的。比如:字典、列表。
不可变的:字符串、整数、元组。
2. 推导式
Comprehension——用于创建集合和可迭代对象的简写语法。
▍列表推导式
[expr(item) for item in iterable]
▍集合推导式
{expr(item) for item in iterable}
▍字典推导式
{key_expr: value_expr for item in iterable}
▍Generator 推导式
(expr(item) for item in iterable)
▍ If-clause 推导式
[expr(item) for item in iterable if predicate(item)]
▍多重推导式
values = [(x, y) for x in range(5) for y in range(3)]
values
相当于
values = []
for x in range(5):
for y in range(3):
values.append((x, y))
values
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2), (3, 0), (3, 1), (3, 2), (4, 0), (4, 1), (4, 2)]
▍嵌套推导式
values = [[y * 3 for y in range(x)] for x in range(10)]
values
相当于
values = []
for x in range(10):
inner = []
for y in range(x):
inner.append(y * 3)
values.append(inner)
values
[[], [0], [0, 3], [0, 3, 6], [0, 3, 6, 9], [0, 3, 6, 9, 12], [0, 3, 6, 9, 12, 15], [0, 3, 6, 9, 12, 15, 18],
[0, 3, 6, 9, 12, 15, 18, 21], [0, 3, 6, 9, 12, 15, 18, 21, 24]]
3. 扩展关键字参数
在Python中调用函数时,通常必须在使用关键字参数和位置参数之间进行选择。
关键字参数通常可用于使函数调用更加明确。
当我们使用关键字参数时:我们通常可以省略具有默认值的参数。
def function_name(arg1, arg2=1.0,):
Body
arg1 => positional argument
arg2 => keyword argument
扩展形式参数语法:
def hyperVolume(*lengths):
i = iter(lengths)
v = next(i)
for length in i:
v *= length
return v
print(hyperVolume(1, 2, 3, 4, 5))
120
扩展参数的数据类型:
*args =>tuple
**kwargs => dict
these arguments should be pass in equence:
def func(arg1, arg2, *args, kwarg1, **kwargv):
print(type(*args))
print(*args)
print(type(**kwargv))
print(**kwargv)
扩展实参语法:
t = (1, 2, 3, 4, 5)
def print_args(arg1, arg2, *args):
print(arg1)
print(type(arg1))
print(arg2)
print(type(arg2))
print(args)
print(type(args))
print_args(*t)
1
<class 'int'>
2
<class 'int'>
(3, 4, 5)
<class 'tuple'>
4. 闭包和装饰器
在开始闭包之前,我们先了解一下local 函数:
适用于特殊的、一次性的功能
使得代码具有组织性和可读性
类似于lambdas,但更为一般
可能包含多个表达式
可能包含statements
▍LEGB含义解释
L-Local(function):函数内的名字空间
E-Enclosing function locals:外部嵌套函数的名字空间(例如closure)
G-Global(module):函数定义所在模块(文件)的名字空间
B-Builtin(Python):Python内置模块的名字空间
Python的命名空间是一个字典,字典内保存了变量名称与对象之间的映射关系,因此,查找变量名就是在命名空间字典中查找键-值对。
Python有多个命名空间,因此,需要有规则来规定,按照怎样的顺序来查找命名空间,LEGB就是用来规定命名空间查找顺序的规则。
LEGB规定了查找一个名称的顺序为:local-->enclosing function locals-->global-->builtin(局部变量———闭包空间———全局变量———内建模块内置)
▍Returning Function
▍闭包
维持对早期范围对象的引用。
我们可以使用_closure__来验证函数是否为闭包。
一个函数和它的环境变量合在一起,就构成了一个闭包(closure)。在Python中,所谓的闭包是一个包含有环境变量取值的函数对象。环境变量取值被保存在函数对象的 __closure__ 属性中。比如下面的代码:
__closure__ 里包含了一个元组。这个元组中的每个元素是cell类型的对象。我们看到第一个cell包含的就是整数15,也就是我们创建闭包时的环境变量b的取值。
下面看一个闭包的实际例子:
这个例子中,函数line与环境变量a,b构成闭包。在创建闭包的时候,我们通过line_conf的参数a,b说明了这两个环境变量的取值,这样,我们就确定了函数的最终形式(y = x + 1和y = 4x + 5)。我们只需要变换参数a,b,就可以获得不同的直线表达函数。由此,我们可以看到,闭包也具有提高代码可复用性的作用。
如果没有闭包,我们需要每次创建直线函数的时候同时说明a,b,x。这样,我们就需要更多的参数传递,也减少了代码的可移植性。利用闭包,我们实际上创建了泛函。line函数定义一种广泛意义的函数。这个函数的一些方面已经确定(必须是直线),但另一些方面(比如a和b参数待定)。随后,我们根据line_conf传递来的参数,通过闭包的形式,将最终函数确定下来。
一个函数闭包是一个函数和一个引用集合的组合,这个引用集合指向这个函数被定义的作用域的变量。后者通常指向一个引用环境(referencing environment),这使得函数能够在它被定义的区域之外执行。在Python中,这个引用环境被存储在一个cell的tuple中。你能够通过func_closure或Python 3中的__closure__属性访问它。要铭记的一点是引用及是引用,而不是对象的深度拷贝。当然了,对于不可变对象而言,这并不是问题,然而对可变对象(list)这点就必须注意。请注意函数在定义的地方也有__globals__字段来存储全局引用环境。
▍装饰器
装饰器是这样一种设计模式:如果一个类希望添加其他类的一些功能,而不希望通过继承或是直接修改源代码实现,那么可以使用装饰器模式。简单来说Python中的装饰器就是指某些函数或其他可调用对象,以函数或类作为可选输入参数,然后返回函数或类的形式。
简单地说,decorator就像一个wrapper一样,在函数执行之前或者之后修改该函数的行为,而无需修改函数本身的代码,这也是修饰器名称的来由。
生成器和迭代协议
▍Iterable:可以将对象传递给内置的iter()函数来获得迭代器。
▍Iterator:可以将对象传递给内置的next()函数来获取下一项。
▍生成器
Python生成器是创建迭代器的一种简单方法。上面提到的都由Python中的生成器自动处理的。
生成器是一个函数,它返回一个对象(迭代器),我们可以遍历该对象(每次一个值)。
如果一个函数包含至少一个yield语句,则它将成为生成器函数。
不同之处在于,虽然return语句完全终止了一个函数,但是yield语句暂停保存函数的所有状态,然后在后续调用时继续执行。
为什么在Python中使用生成器?
Easy to Implement
Memory Efficient
Represent Infinite Stream
Pipelining Generators
上下文管理器
▍ContextManager:上下文管理器就是实现了上下文管理协议的对象。主要用于保存和恢复各种全局状态,关闭文件等,上下文管理器本身就是一种装饰器。
▍__enter__ ()
在进入with-statement主体之前调用
返回绑定到变量的值
可以返回任何类型的值
通常返回上下文管理器本身
▍__exit__()
当语句体退出时调用
__exit__(self, exc_type, exc_val, exc_tb)
@staticmethod、 @classmethod
如果需要访问函数中的类属性,请使用@classmethod。
如果不需要使用cls对象,则使用@static method。
与其他语言不同,Python中的静态方法可以在子类中重写。
继承和封装
▍继承
继承是一个类获取另一个类的属性的机制。例如,一个孩子继承了他/她父母的特点。通过继承,我们可以重用现有类的字段和方法。因此,继承促进了可重用性,并且是OOPs的一个重要概念。
▍单继承
子类将具有基类的所有功能,还可以修改和增强。
子类初始化器希望调用基类初始化器,以使整个对象被初始化。
调用其他类初始化器:
1、其他语言自动调用base class初始化器
2、Python像对待其他方法一样处理 _init__()
3、base class _init__()在被覆盖时不会被调用
4、使用super()调用 base class _init__()
isinstance(instance, class):确定对象是否具有指定的类型。
Issubclass(subclass,base class):确定一个类型是否是其他类型的子类。
▍多继承
即子类有多个父类,并且具有它们的特征:
Python如何知道应该调用哪个base class函数?
Python使用方法解析Order和super来做到这一点。
方法解析顺序
确定方法名称查找的顺序
1、通常称为“MRO”
2、方法可以在多个地方定义
3、MRO是继承图的排序
▍封装
Python包和程序设计
Sys.path Python搜索模块的目录列表。
PYTHONPATH 添加到sys.path的环境变量列表路径。
1、包是包含其他模块的模块。
2、包通常实现为包含特殊 _init__.py 文件的目录。
3、导入包时执行 __init__.py 文件。
4. 包可以包含自己实现的子包。这些子包本身是用目录中的 __init__.py 文件实现的。
5、包的模块对象具有__path__属性。
绝对导入:使用模块完整路径的导入。比如 import a,Python 会在 sys.path 里寻找所有名为 a 的顶层模块。
相对导入:使用相同包中模块的相对路径的导入。比如一个 package 下有 a.py 和 b.py 两个文件,在 a.py 里 from . import b 即是相对导入 b.py。
__all__:是一个字符串list,用来定义模块中对于from XXX import *时要对外导出的符号,即要暴露的借口,但它只对import *起作用,对from XXX import XXX不起作用。
来自:https://medium.com/@agrawal.pulkit1994
—End—
量化投资与机器学习微信公众号,是业内垂直于Quant、MFE、CST等专业的主流自媒体。公众号拥有来自公募、私募、券商、银行、海外等众多圈内10W+关注者。每日发布行业前沿研究成果和最新资讯。
阅读 3354 在看3
精选留言
写留言
2
林万程
看到这个标题就觉得想说的是:在座的各位都是垃圾
1 作者
chengyj我爱我老婆
好文
作者
欢迎多多分享哦😃😃
Virnoie
标题的重点的中级程序员
作者