入门python好博客
进阶大纲
有趣的灵魂
老齐的教程
老齐还整理了很多精华
听说 fluent python + pro python 这两本书还不错!
元组三种遍历,有点像回字有四种写法一样。。。苦笑
1 | for index in range(0,len(tuple_1)): |
1 | tuple 互转 tuple(list_1) , list(tuple_2) |
- 列表生成式 vs 生成器表达式
1 | >>> [x for x in list_1 if x%2==1] |
迭代器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
27Generator 天然的 迭代器
而 tuple , list 等 序列如果要编程 迭代器 需要 iter(list_1) 、iter(tuple_2)
>>> from collections import Iterator
>>> isinstance((1,2,3,4),Iterator)
False
>>> isinstance((x for x in range(10) if x%2==0),Iterator)
True
>>>
>>> isinstance(iter((1,2,3,4)),Iterator)
True
>>>
>>> list_1 = [1,2,3,4]
>>> list_1_iter = iter(list_1)
>>> while True:
... try:
... x=next(list_1_iter)
... print('x:{}'.format(x))
... except StopIteration as e:
... print('e.value: {}'.format(e.value))
... break
...
x:1
x:2
x:3
x:4
e.value: None
- python map reduce 实现
1 | >>> def pow2(val): |
- 注意区别 Iterable 可迭代 与 Iterator 惰性迭代器
高阶函数
1 | >>> def lazy_sum(*args): |
##win 下 python 清屏1
2
3
4
5
6
7
8
9
10
11>>> import os
>>> def clear():
... os.system('cls')
>>> import os
>>> def cls():
... if os.name.upper() == 'NT':
... os.system('cls')
... else:
... os.system('clear')
可变参数,巧调用
##python的可变参数和关键字参数(*args **kw)
##讲*args 可变参数, **kw 关键字参数非常好的文章
1 | >>> def test(*args): |
##装饰器类似于 java 里的 AOP 动态代理,或者继承组合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>>> import functools
>>> #自定义文本消息的事务装饰器
... def trans(text):
... def decorater(func):
... @functools.wraps(func)
... def wrapper(*args,**kw):
... print('{} {}'.format(text,func.__name__))
... return func(*args,**kw)
... return wrapper
... return decorater
...
>>> @trans('开启事务'):
File "<stdin>", line 1
@trans('开启事务'):
^
SyntaxError: invalid syntax
>>> @trans('开启事务')
... def trans_func():
... print('我是一个要被事务装饰的函数')
...
>>> trans_func()
开启事务 trans_func
我是一个要被事务装饰的函数
>>> from functools import wraps
>>> def my_decorator(func):
... @wraps(func)
... def wrap_func():
... print('before...')
... func()
... print('after...')
... return wrap_func
...
>>> @my_decorator
... def func_a():
... print('func_a...')
...
>>> func_a()
before...
func_a...
after...
>>> func_a.__name__
'func_a'
>>> from functools import wraps
>>> def custom_text(text):
... def decorater(func):
... @wraps(func)
... def wrap_decorated(*args,**kwargs):
... print('{} {}'.format(text,func.__name__))
... return func(*args,**kwargs)
... return wrap_decorated
... return decorater
...
>>> @custom_text('自定义文本信息...')
... def tran(*args,**kwargs):
... for i in args:
... print(i,end=',')
... for key,value in kwargs.items():
... print('{}-->{}'.format(key,value))
... print('事务...社会...')
...
>>> args = (1,'abc',3)
>>> from functools import wraps
>>> kwargs = dict(name='Frank',age=18)
>>> tran(*args,**kwargs)
自定义文本信息... tran
1,abc,3,name-->Frank
age-->18
事务...社会...
from functools import wraps
class LogIt(object):
def __init__(self,log_file='out.log'):
self._log_file = log_file
@property
def log_file(self):
return self._log_file
@log_file.setter
def log_file(self,log_file):
self._log_file = log_file
def __call__(self,func):
@wraps(func)
def wrap_func(*args,**kwargs):
log_string = '{} {}'.format(func.__name__,'called...')
print('wrap_func logging...{}'+log_string)
with open(self.log_file,'a') as logfile:
logfile.write(log_string+'\n')
self.notify(log_string)
return func(*args,**kwargs)
return wrap_func
def notify(self,log_string):
print('notify logging...{}'.format(log_string))
@LogIt('out1.log')
def trans(*args,**kwargs):
for i in args:
print(i,end=',')
for key,value in kwargs.items():
pritn('{}<-->{}'.format(key,value))
args = ('trans start..',1,2,'test')
kwargs = dict(name='Frank',age=18)
trans(*args,*kwargs)
wrap_func logging...{}trans called...
notify logging...trans called...
trans start..,1,2,test,name,age,
##偏函数,可以见 functools 多么强大值得好好学学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>>> convert_int_from_8 = functools.partial(int,base=8)
>>> convert_int_from_8(12345)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: int() can't convert non-string with explicit base
>>> convert_int_from_8('12345')
5349
# kw 这种 dict 传值也是可以的
>>> kw = {'base':8}
>>> convert_int_from_8 = functools.partial(int,base)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'base' is not defined
>>> convert_int_from_8 = functools.partial(int,**kw)
>>> convert_int_from_8('123456')
最后,创建偏函数时,实际上可以接收函数对象、*args和**kw这3个参数,当传入:
int2 = functools.partial(int, base=2)
实际上固定了int()函数的关键字参数base,也就是:
int2('10010')
相当于:
kw = { 'base': 2 }
int('10010', **kw)
当传入:
max2 = functools.partial(max, 10)
实际上会把10作为*args的一部分自动加到左边,也就是:
max2(5, 6, 7)
相当于:
args = (10, 5, 6, 7)
max(*args)
结果为10。
# 总结 就是 偏函数 其实就是把原本参数很多的函数简化参数,便于使用
#当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单
##模块1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# -*- coding: utf-8 -*-
'test module'
__author__ = 'Frank Li'
import sys
def test():
args=sys.argv
if len(args)==1:
print('hello world!')
elif len(args)==2:
print('hello {}'.format(args[1]))
else:
print('to many args!')
if __name__ == '__main__':
test()
##模块搜索路径1
2
3
4
5
6
7
8
9
10
11
12
13
14默认情况下,Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys模块的path变量中:
>>> import sys
>>> sys.path
['', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6', ..., '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages']
如果我们要添加自己的搜索目录,有两种方法:
一是直接修改sys.path,添加要搜索的目录:
>>> import sys
>>> sys.path.append('/Users/michael/my_py_scripts')
这种方法是在运行时修改,运行结束后失效。
第二种方法是设置环境变量PYTHONPATH,该环境变量的内容会被自动添加到模块搜索路径中。设置方式与设置Path环境变量类似。注意只需要添加你自己的搜索路径,Python自己本身的搜索路径不受影响。
面向对象
1 | >>> class Test(object): |
##再进一阶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>>> class Person(object):
... def __init__(self,name,age,*args,**kw):
... self.name,self.age = name,age
... for arg in args:
... print('arg: {}'.format(arg))
... for key in kw:
... print('key: {}--> value: {}'.format(key,kw[key]))
...
>>> args=('a',1,2,'b')
>>> kw ={'city':'changsha','job':'developer'}
>>> Person('frank',18,*args,**kw)
arg: a
arg: 1
arg: 2
arg: b
key: city--> value: changsha
key: job--> value: developer
<__main__.Person object at 0x02F00DD0>
>>> class Student(object):
... def __init__(self,name,score,*args,**kw):
... self.name,self.score = name,score
... for arg in args:
... print('arg: {}'.format(arg))
... for key in kw:
... if key=='city':
... self.city =kw[key]
... elif key=='job':
... self.job=kw[key]
... else:
... pring('key: {} --> value: {}'.format(key,kw[key]))
... def get_grade(self):
... if self.score >= 90:
... return '优'
... if 70<self.score<90:
... return '良'
... elif 60<self.score<=70:
... return '几个'
... else:
... return '不及格'
>>> student = Student('frank',80,*args,**kw)
arg: a
arg: 1
arg: 2
arg: 3
arg: c
arg: d
>>> student.city
'changsha'
>>> student.get_grade()
'良'
>>>
区别于 java 这种静态语言 , python 是动态语言
小结
类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响;
方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;
通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节。
和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同:
>>> bart = Student('Bart Simpson', 59)
>>> lisa = Student('Lisa Simpson', 87)
>>> bart.age = 8
>>> bart.age
8
>>> lisa.age
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'age'
访问权限控制
1 | 此方法不推荐, 应该用 set_gender() 而不是 bart._Student__gender 这种方式修改 gender 属性 |
以为是多态,然而是多态,更不止是多态, 只要有 run 方法的 对象 都可以 往里丢 ,这一点注意区分 java 的 接口以及父类
1 | >>> class Animal(object): |
类型判断 type vs isinstance ==》 isinstance 胜 !!! 总是优先使用 isinstance 判断
1 | >>> type(123) == int |
getter setter
1 | >>> class Student(object): |
##记住标准写法就好,别追问,会晕!!!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>>> class Student(object):
... def __init__(self,name,score,*args,**kw):
... self._name = name
... self._score = score
... if len(args)!=0:
... self.arg = args[0]
... for key in kw:
... if key == 'city':
... self.city = kw[key]
... @property
... def name(self):
... return self._name
... @name.setter
... def name(self,name):
... self._name = name
... @property
... def score(self):
... return self._score
... @score.setter
... def score(self,score):
... self._score = score
...
>>> args=('a',1,2)
>>> kw = {'city':'changsha','job':'unknown'}
>>> s = Student('frank',100,*args,**kw)
>>> s.name
'frank'
>>> s.score
100
>>> s.city
'changsha'
>>> s.arg
'a'
>>> class Student(object):
... def __init__(self,name,age,score,*args,**kw):
... self._name=name
... self._age = age
... self._score = score
... if len(args)!=0:
... self.arg = args[0]
... for key in kw:
... if key == 'city':
... self.city = kw[key]
... @property
... def name(self):
... return self._name
... @name.setter
... def name(self,name):
... self._name = name
... @property
... def age(self):
... return self._age
... @age.setter
... def age(self,age):
... if not isinstance(age,int):
... raise TypeError('年龄必须为整数!')
... else:
... self._age = age
... @property
... def score(self):
... return self._score
... @score.setter
... def score(self,score):
... if not isinstance(score,int):
... raise TypeError('分数应该为整数!')
... elif not 0<= score <= 100:
... raise ValueError('分数必须介于0-100之间!')
... else:
... self._score = score
...
>>> s = Student('frank',18,100)
>>> s.name
'frank'
>>> s.age
18
>>> s.score
100
多继承 ,对应 java extends class implements Runnable 这种写法, 只是 python 木有 接口一说 貌似,我也不确定哈,自己去查查吧
1 | >>> class Animal(): |
定制类
1 | # __slot__ 固定 self 属性个数 |
枚举类
1 | >>> from enum import Enum |
##枚举类与错误综合小例子1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20>>> class Student(object):
... def __init__(self,name,gender):
... if not isinstance(gender,Gender):
... raise TypeError('{}'.format('传入的性别类型异常'))
... self.__name = name
... self.gender = gender
...
>>> bart = Student('Bart', Gender.Male)
>>> if bart.gender == Gender.Male:
... print('测试通过!')
... else:
... print('测试失败!')
...
测试通过!
>>> bart = Student('Bart', '男')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __init__
TypeError: 传入的性别类型异常
>>>
元类,我服了!!!
推荐一篇高分文章读懂元类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>>> def fn(self,world = 'world!'):
... print('hello {}'.format(world))
...
>>> Hello = type('Hello',(object,),dict(hello = fn))
>>> h = Hello()
>>> h.hello()
hello world!
>>> class ListMetaclass(type):
... def __new__(cls,name,bases,attrs):
... attrs['add']=lambda self,value:self.append(value)
... return type.__new__(cls,name,bases,attrs)
...
>>> class MyList(list,metaclass=ListMetaclass):
... pass
...
>>> l = MyList()
>>> l.add(5)
>>> l
[5]
# 类是一种特殊的对象,因为python 是动态语言,可以后期绑定属性方法等
>>> class ObjectCreator():
... pass
...
>>> print(ObjectCreator)
<class '__main__.ObjectCreator'>
>>> print(hasattr(ObjectCreator,'new_attribute'))
False
>>> ObjectCreator.new_attribute = 'foo'
>>> print(hasattr(ObjectCreator,'new_attribute'))
True
>>> ObjectCreatorMirror = ObjectCreator
>>> print(ObjectCreatorMirror())
<__main__.ObjectCreator object at 0x00859A30>
异常处理
1 | >>> def div(a,b): |
既然如此重要,再谈元类
1 | # 定义一个函数,用来待会儿在 类 内部或绑定,或调用 |
IO , 文件 , 内存, 字符,字节 类似于 java 的 IO
1 | import os |
file name: mock_data.csv
mock_data <-----> .csv----->
加上 编码,解码方式
1 | file_list = os.listdir('.') |
文件夹目录以及文件相关操作
1 | # 在当前路径下查找包含指定字符串的 所有文件名,并返回。如果是子目录,需要用到递归,没有写,有空写写 |
序列化 (内存流向磁盘的过程)与 反序列化(磁盘流向内存的过程)
1 | # 序列化 |
序列化为json 串存储到磁盘, 反序列化从磁盘读取 json 串到内存转化为python对象
1 | import json |
再进一阶,序列化与反序列化 json 串 between 对象
1 | import json |
小结
Python语言特定的序列化模块是pickle,但如果要把序列化搞得更通用、更符合Web标准,就可以使用json模块。
json模块的dumps()和loads()函数是定义得非常好的接口的典范。当我们使用时,只需要传入一个必须的参数。但是,当默认的序列化或反序列机制不满足我们的要求时,我们#### 又可以传入更多的参数来定制序列化或反序列化的规则,既做到了接口简单易用,又做到了充分的扩展性和灵活性。
##内建模块以及常用第三方模块1
2
3
4
5
6
7
8
9
10
11
12
13
14import urllib.request as urllib2
import random
ua_list=["Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv2.0.1) Gecko/20100101 Firefox/4.0.1",
"Mozilla/5.0 (Windows NT 6.1; rv2.0.1) Gecko/20100101 Firefox/4.0.1",
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
"Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"]
u_agent = random.choice(ua_list)
# print(u_agent)
url = 'http://www.baidu.com'
request = urllib2.Request(url=url)
request.add_header("User_agent",u_agent)
response = urllib2.urlopen(request)
print(response.read())
其他
1 | 标准数据类型 |
python 日志
1 | # 这段代码保存为 config.py |
引用上段代码保存的额 config.py 文件里的module
1 | __author__ = 'Frank Li' |
编码规范 , 变量定义
1 | # Python变量命名用法(一般变量、常量、私有变量、内置变量) |
字典操作 dict_1.update(dict_2) 合并 dict
1 | dict_1 = {'name':'Frank','age':18} |
字典推导式
1 | mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3} |
由 两个 list 合并 dict 原理是利用 zip 合并成 ((key1,value1),(key2,value2)) 然后用 dict[key] = value 方式
1 | list_1 = ['name','age'] |
list 去重
1 | # 方法一 |
列表排序
1 | 列表排序 |
列表并行排序
1 | list_1 = [8,4,3,2,7,6,5] |
模拟 with open
1 | >>> class File(object): |
类似于 scala 的 flattern 列表展平
1 | >>> import itertools |
for - else 结构
1 | for n in range(2, 100): |
1 | # 替代 switch case 方案 字典映射 |
16.检查一个字符串是否是一个数字?1
2
3
4
5
6
7
8
9
10
11In[22]: x = '569789'
In[23]: x.isdigit()
Out[23]: True
In[24]: y = 'gdf2667'
In[25]: y.isdigit()
Out[25]: False
17.查找列表中某个元素的下标?1
2
3In[26]: ['a','b','c'].index('b')
Out[26]: 1
18.如何在列表中随机取一个元素?
1 | import random |
1 | # 字典排序 |
JAVA vs PYTHON (还没细看)
总结:
至此,关于 python 基础的总结基本完结,其中有涉及到高阶知识 , 元类,位置参数关键字参数 可变参数(*args type: tuple,**kwargs type: dict),
生成器,装饰器,函数式编程风格的 map reduce filter sorted上下文管理器, 要补充的有 : 进程线程协程,异步io
接下来的时间应该是 学习 python 的重要常用模块(Pandas,Numpy,Scipy,PIL pillow , opencv,sk-learn,xgboost,爬虫库 scrappy等)以及框架(Django)
最后感慨一下,如果一开始碰到了python 也许根本就不会去学java了,感觉python的设计思想比较符合我的思想各种黑魔法的魅力吸引着我!!!
(虽然java不可否认也是一门优雅的工程化设计语言但不够精简,语法冗长)。。。life is short , I use python and java ! 其实语言本身没有好坏,
只有适用场景(多一门语言能力便多一种工具,而工具可以提高效率!),我曾经还一直在想为什么没有出现一门语言一统天下呢 现在想想也是天真。。。
不过语言始终流于招式,接下来是要修炼一波内功了,算法才是灵魂!