python学习笔记

该文章记录廖雪峰网站上的学习笔记:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143178254193589df9c612d2449618ea460e7a672a366000

 


基础:
python命令退出的方法是exit()
Python的解释器很多,但使用最广泛的还是CPython。
Python交互模式主要是为了调试Python代码用的,也便于初学者学习,它不是正式运行Python代码的环境!python+file.py时,要放到file.py文件的目录下执行;
文本编辑器:一个是Sublime Text,免费使用,但是不付费会弹出提示框:一个是Notepad++,免费使用,中文界面:


Python的交互模式和直接运行.py文件有什么区别呢?
直接输入python进入交互模式,相当于启动了Python解释器,但是等待你一行一行地输入源代码,每输入一行就执行一行。
直接运行.py文件相当于启动了Python解释器,然后一次性把.py文件的源代码给执行了,你是没有机会以交互的方式输入源代码的。
用Python开发程序,完全可以一边在文本编辑器里写代码,一边开一个交互式命令窗口,在写代码的过程中,把部分代码粘到命令行去验证,事半功倍!前提是得有个27'的超大显示器!




eclipse下python开发环境




python基础---数据类型和变量:
python数据类型有:整数、浮点数、字符串、布尔值、空值、变量、常量


print(r'\\\'')  用r''默认可以不转义;
print('''line
line2
line3''')    '''''' 表示多行输出,否则不能多行输出;




布尔值:True  or False  ; True  and False;
布尔值可以用and、or和not运算。
空值
空值是Python里一个特殊的值,用None表示。None不能理解为0,因为0是有意义的,而None是一个特殊的空值。
此外,Python还提供了列表、字典等多种数据类型,还允许创建自定义数据类型,






#-*- coding:utf-8 -*-
a = 123
print (a)
a = 'ABC'
print (a)


变量:动态变量和静态变量,java的变量定义是静态变量,
这种变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错。例如Java是静态语言,赋值语句如下(// 表示注释):


动态变量:a = 123 其实是创建了整数123和一个变量a,并让a指向123,如果再a  =  'ABC',则是a重新指向了字符串ABC


常量:
所谓常量就是不能变的变量
除法:/和//  ,前者除后是浮点数,后者是整除取整数。
%是取余;


该章小节:
Python支持多种数据类型,在计算机内部,可以把任何数据都看成一个“对象”,而变量就是在程序中用来指向这些数据对象的,对变量赋值就是把数据和变量给关联起来。

字符串和编码:
字符编码:
Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。
Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。
为了解决“用Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上就十分不划算。”的问题,把Unicode编码转化为“可变长编码”的UTF-8编码。
在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。
用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件:


Python的字符串:
在最新的Python 3版本中,字符串是以Unicode编码的,也就是说,Python的字符串支持多语言,例如:
对于单个字符的编码,Python提供了ord()函数获取字符的整数表示,chr()函数把编码转换为对应的字符:


格式化:


最后一个常见的问题是如何输出格式化的字符串。我们经常会输出类似'亲爱的xxx你好!你xx月的话费是xx,余额是xx'之类的字符串,而xxx的内容都是根据变量变化的,所以,需要一种简便的格式化字符串的方式。
你可能猜到了,%运算符就是用来格式化字符串的。在字符串内部,%s表示用字符串替换,%d表示用整数替换,有几个%?占位符,后面就跟几个变量或者值,顺序要对应好。如果只有一个%?,括号可以省略。
常见的占位符:
占位符
替换内容
%d   整数
%f    浮点数
%s    字符串
%x   十六进制整数




格式化整数和浮点数还可以指定是否补0和整数与小数的位数:
print( '%f ' % 3.1415926)  输出是3.141593 
print( '%2f ' % 3.1415926)  输出是3.141593 
print( '%.2f ' % 3.1415926)  输出是3.14    这个是补足小数位数为2位。


些时候,字符串里面的%是一个普通字符怎么办?这个时候就需要转义,用%%来表示一个%:
print('growth rate: %d%% '  % 7 ) 输出是growth rate: 7% 

format()
另一种格式化字符串的方法是使用字符串的format()方法,它会用传入的参数依次替换字符串内的占位符{0}、{1}……,不过这种方式写起来比%要麻烦得多:
print('Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125))

疑惑点:{1:.1f} 其中1:冒号后面就是说明该字符串的格式的?是以小数点后1位展示;
课后题:
s1 = 72
s2 = 85
s=s2 - s1
print('Hello, {0}, 成绩提升了 {1:.1f} 分'.format('小明', s))
输出结果是:
Hello, 小明, 成绩提升了 13.0 分

使用list和tuple
如果要取最后一个元素,除了计算索引位置外,还可以用-1做索引,直接获取最后一个元素:
以此类推,可以获取倒数第2个、倒数第3个:
classmates=['df','wangyilin','yushao']
classmates[-1]  是倒数第一个,classmates[-2] 是倒数第二个

list可以是二维、三维、四维属组;
list是一个可变的有序表,所以,可以往list中追加元素到末尾,也可以插入元素到对应的位置、删除元素、更换元素

classmates.append('xiaohua')   list最后追加一个元素,值为xiaohua
classmates.insert(1,'xiaohua')   在索引为1的位置上,插入一个元素,值为xiaohua
classmates.pop()删除list中最后一个元素
classmates.pop(i)删除list中索引为i的一个元素,其中i是索引位置:
classmates[1] = 'Sarah'    更换元素中的值
tuple
另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改,比如同样是列出同学的名字:
list和tuple是Python内置的有序集合,一个可变,一个不可变。根据需要来选择使用它们。
当tuple可变时,其实就是tuple中对应位置的内容发生了变更;
最后来看一个“可变的”tuple:是元组中包含数组
>>> t = ('a', 'b', ['A', 'B'])
>>> t[2][0] = 'X'
>>> t[2][1] = 'Y'
>>> t
(
('a', 'b', ['X', 'Y'])


条件判断:
一定注意冒号,不要少了;
if <条件判断1>:
 
    <执行1>

elif <条件判断2>:
 
    <执行2>
elif <条件判断3>:

    <执行3>
else:
 
    <执行4>

if判断语句的简写如下:
if x:
 
    print('True')

age = 18
if age >= 18:
    print('your age is', age)
    print('adult')
else:
    print('your age is', age)
    print('teenager')
最后看一个有问题的条件判断。很多同学会用input()读取用户的输入,这样可以自己输入,程序运行得更有意思:
input()函数
birth=input()
if birth < 2000 : 
    print("非 00 后")
elif  birth >= 2000:
    print(" 00 后")

课后题:
height = 1.75
weight = 80.5
a=height*height
bmi=weight/a
print(bmi)
if bmi < 18.5 :
    print("your are too thin")
elif bmi<25 :
    print("your are healthy")
elif bmi<28 :
    print("your are a little fat")   
elif bmi<32 :
    print("your are fat")   
else  :
    print("your are  too  fat")

循环:
所以for x in ...循环就是把每个元素代入变量x,然后执行缩进块的语句。
主要是:for、while、break(提前结束当前循环)、continue(循环内后面的语句不执行,直接进行下次循环)
#-*- coding:utf-8 -*-
sum = 0
for  x  in range(101):
    sum = sum + x
print(sum)

sum2 = 0
i = 99
while  i > 0 :
    sum2 = sum2 + i
    i = i - 2
print(sum2)


L = ['Bart', 'Lisa', 'Adam']
for i in range(3) :
    print("hello",L[i])


sum2 = 0
i = 99
while  i > 0 :
    sum2 = sum2 + i
    i = i - 2
    if i < 50 :
        break
print(i)
print(sum2)
打印结果是:
49
1875


n = 0
while n < 10 :
    n = n +1 
    if n % 2 == 0 : # 如果n是偶数,执行continue语句
         continue    continue语句会直接继续下一轮循环,后续的print()语句不会执行
    print(n)

小结
循环是让计算机做重复任务的效的方法。
break语句可以在循环过程中直接退出循环,而continue语句可以提前结束本轮循环,并直接开始下一轮循环。这两个语句通常都必须配合if语句使用。
要特别注意,不要滥用break和continue语句。break和continue会造成代码执行逻辑分叉过多,容易出错。大多数循环并不需要用到break和continue语句,上面的两个例子,都可以通过改写循环条件或者修改循环逻辑,去掉break和continue语句。
些时候,如果代码写得问题,会让程序陷入“死循环”,也就是永远循环下去。这时可以用Ctrl+C退出程序,或者强制结束Python进程。


dict 和set
Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。

>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d['Michael']
95
二是通过dict提供的get()方法,如果key不存在,可以返回None,或者自己指定的value:
>>> d.get('Thomas')


>>> d.get('Thomas', -1)
-
-1
要删除一个key,用pop(key)方法,对应的value也会从dict中删除:

set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。
重新赋值:
d['M']=100
两种判断key是否存在的方法:
 一是通过in判断key是否存在:'M'  in d
二是通过dict提供的get()方法,如果key不存在,可以返回None,或者自己指定的value:
>>> d.get('Thomas')

>>> d.get('Thomas', -1)
-1
删除一个key,用pop(key)
d.pop('M')
请务必注意,dict内部存放的顺序和key放入的顺序是没有关系的。
所以,dict是用空间来换取时间的一种方法。
第一条就是dict的k ey必须是不可变对象。
set
set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,即使key重复,在打印时,有而不会出现,所以,在set中,没有重复的key。
set的输入组合是list:
>>> s=set([1,2,4])
>>> s
set([1, 2, 4])

加入元素:通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果:
删除元素:remove(key)方法可以删除元素:


set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:
>>> s1=set([1,2,3,4])
>>> s2=set([2,3,4,5])
>>> s1&s2
set([2, 3, 4])
>>> s1|s2
set([1, 2, 3, 4, 5])


不可变对象:list是可变对象,str是不变对象。对于不变对象来说,调用对象自身的任意方法,也不会改变该对象自身的内容。
>>> a
['a', 'b', 'c']
>>> a=['d','c','b']
>>> a.sort()
>>> a
['b', 'c', 'd']
>>> a='bcd'
>>> a.replace('b','B')
'Bcd'
>>> a
'bcd'


小结
使用key-value存储结构的dict在Python中非常有用,选择不可变对象作为key很重要,最常用的key是字符串。
tuple虽然是不变对象,但试试把(1, 2, 3)和(1, [2, 3])放入dict或set中,并解释结果。
 

函数:

python自身内置了很多函数:

绝对值最大最小值函数、数据转换函数

Python内置的常用函数还包括数据类型转换函数,比如int()函数可以把其他数据类型转换为整数:
hex()函数把一个整数转换成十六进制表示的字符串:
函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”:
>>> a= abs
>>> a(-1)
1
小节:
调用Python的函数,需要根据函数定义,传入正确的参数。如果函数调用出错,一定要学会看错误信息,所以英文很重要!


函数格式,重要元素有:函数名、参数、和冒号
def   function_name(param1,param2):
        if  n  < 0 :
             return  param1  


函数的参数:位置参数、默认参数、可变参数、关键字参数、参数组合
规则:
一是必选参数在前,默认参数在后,否则Python的解释器会报错(思考一下为什么默认参数不能放在必选参数前面);
二是如何设置默认参数。
当函数多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。


修改后的power(x, n)函数两个参数:x和n,这两个参数都是位置参数,调用函数时,传入的两个值照位置顺序依次赋给参数x和n。
def power(x,n):
    s=1
    while n > 0 :
        s=s*x
        n=n-1
    return s
power(5,3)
125
从上面的例子可以看出,默认参数可以简化函数的调用。设置默认参数时,几点要注意:


使用默认参数什么好处?最大的好处是能降低调用函数的难度。
 定义默认参数要牢记一点:默认参数必须指向不变对象!


可变参数
在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。
python2.7版本里,下面的只支持list格式:
def calc(numbers):
    sum = 0
    for n in numbers:
        sum = sum + n*n
    return sum
python2.7版本里,下面的只支持tuple格式:
def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n*n
    return sum


在python3中,上述两种同时支持list和tuple


对于已经有了一个list或者tuple,要调用一个可变参数:
>>> nums=[1,2,3]
>>> calc(nums[0],nums[1],nums[2])
14
简单的方法是:
*nums表示把nums这个list(或者tuple)的所有元素作为可变参数传进去。
>>> nums=[1,2,3]
>>> calc(*nums)
14


>>> nums=(1,2)
>>> calc(*nums)
5
>>> nums=[1,2]
>>> calc(*nums)
5




关键字参数:**kw
可以传入不受限制的参数,这些参数均被写入到**kw对应的字段中:是以字典类型展示
可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。请看示例:

命名关键字参数必须传入参数名:
防止出现无限制传入参数,
对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些,就需要在函数内部通过kw检查。
命名关键字参数,在参数前要加上*号,*后面的参数被视为命名关键字参数。
如果函数定义中已经了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了;

如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。这种方式定义的函数如下:
def person(name, age, *, city, job):
    print(name, age, city, job)

参数组合
在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。在函数调用的时候,Python解释器自动按照参数位置和参数名把对应的参数传进去。

命名关键字参数、关键字参数;
两者的区别

比如定义一个函数,包含上述若干种参数:
def f1(a, b, c=0, *args, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
def f2(a, b, c=0, *, d, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
    
f1('name','dfs',9)
f1(2,3,9)
f1('name','dfs',9,[1,2,3],(6,7,8))


使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。可以试试fact(1000):

使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。
针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。
Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。

高级特性:
但是在Python中,代码不是越多越好,而是越少越好。代码不是越复杂越好,而是越简单越好。
切片
 

之所以是笨办法是因为扩展一下,取前N个元素就没辙了。
取前N个元素,也就是索引为0-(N-1)的元素,可以用循环:
>>> r = []
>>> n = 3
>>> for i in range(n):
...     r.append(L[i])
... 
>>> r
[
['Michael', 'Sarah', 'Tracy']


对这种经常取指定索引范围的操作,用循环十分繁琐,因此,Python提供了切片(Slice)操作符,能大大简化这种操作。
对应上面的问题,取前3个元素,用一行代码就可以完成切片:
>>> L[0:3]
['Michael', 'Sarah', 'Tracy']


L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2,正好是3个元素。
如果第一个索引是0,还可以省略:
>>> L[:3]
['Michael', 'Sarah', 'Tracy']


也可以从索引1开始,取出2个元素出来:
>>> L[1:3]
['Sarah', 'Tracy']

 




类似的,既然Python支持L[-1]取倒数第一个元素,那么它同样支持倒数切片,试试:
>>> L[-2:]
['Bob', 'Jack']
>
>>> L[-2:-1]
['Bob']


记住倒数第一个元素的索引是-1。
切片操作十分用。我们先创建一个0-99的数列:
>>> L = list(range(100))


>>> L
[
[0, 1, 2, 3, ..., 99]




 比如前10个数:
>>> L[:10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


后10个数:
>>> L[-10:]
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]


前11-20个数:
>>> L[10:20]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]


前10个数,每两个取一个:
>>> L[:10:2]
[0, 2, 4, 6, 8]

列表拷贝的方法:

f=[a,b,c]

ff=f[:]

 

一个列表反转的方法:

f=[a,b,c]

利用步长是-1来解决问题。

ff=f[::-1]


列表生成式:
写列表生成式时,把要生成的元素x * x放到前面,后面跟for循环,就可以把list创建出来,十分有用,多写几次,很快就可以熟悉这种语法。
很多for循环都可以变成一个多个变量生成一个list,只是原来for中print里的逗号,到list中就变成+;
字典中参数的引用是 d.items():

>>> [ x * x for  x  in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
还可以使用两层循环,可以生成全排列:3层和3层以上的循环就很少用到了。
>>> [ m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

运用列表生成式,可以写出非常简洁的代码。例如,列出当前目录下的所文件和目录名,可以通过一行代码实现:
>>> import os
>>> [d  for d in os.listdir('.')]
['nohup.out', 'redis_dcp_2.1.1.tar', 'tmp', '.tcshrc', '.ansible', 'k8s_uninstall.sh', '.oracle_jre_usage', 'java.sh', '.pki', '.bash_profile', '.lesshst', '.viminfo', '.cshrc', 'HDP-2.3.4.7-centos7-rpm.tar.gz', 'openssl-libs-1.0.1e-42.el7_1.9.x86_64.rpm', 'slider-agent.tar.gz', '.bash_history', 'docker-engine-selinux-1.9.1-1.el7.centos.noarch.rpm', 'nginx-1.10.2-1.el7.ngx.x86_64.rpm', 'jdk-7u76-linux-x64.tar.gz', '.bash_logout', 'hosts', '.docker', 'AMBARI-2.2.1.1-70-centos7.tar.gz', 'HDP-UTILS-1.1.0.20-centos7.tar.gz', '.ssh', '.bashrc', 'docker-engine-1.9.1-1.el7.centos.x86_64.rpm', 'anaconda-ks.cfg']

for循环其实可以同时使用两个甚至多个变量,比如dict的items()可以同时迭代key和value:

>>> L = ['Hello', 'World', 'IBM', 'Apple']
>>> [s.lower() for s in L]
['hello', 'world', 'ibm', 'apple']

练习题:如果list中既包含字符串,又包含整数,由于非字符串类型没有lower()方法,所以列表生成式会报错:
r = []
L=['Hello', 'World', 18, 'Apple', None]
for  s  in L:
     if  isinstance(s,str):
         r.append(s.lower())
     r.append(s)
print(r)


但是执行结果生成的字符串中,既有处理后的字符串,又有处理前的字符串。


处理结果是:['hello', 'Hello', 'world', 'World', 18, 'apple', 'Apple', None]


更改如下:要严格按照语法格式敲代码才可以,上面结果错误原因是语法不对;
r = []
L=['Hello', 'World', 18, 'Apple', None]
for  s  in L:
     if  isinstance(s,str):
         print(s.lower())
         r.append(s.lower())
         print(r)
     else :
        r.append(s)
        print(r)
print(r)

生成器
在循环过程中不断的推算出后面的元素,生成列表,这种一遍循环,一边计算的机制,叫做生成器:generator;
定义生成器有两种方法:
我们基本上从来不会用next()来获取下一个返回值,
第二种方法是:
这就是定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:
这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
 回到fib的例子,我们在循环过程中不断调用yield,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。


更改为generator的斐波那契数列,需要多次调用才能跑完整个函数,但是原来的函数,只需要一次调用就可以跑完整个函数。


该节的杨辉三角暂时未写;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值