python基础

python基础

1.序列

序列有两种:tuple(定值表; 也有翻译为元组) 和 list (表)

>>>s1 = (2, 1.3, 'love', 5.6, 9, 12, False)         # s1是一个tuple

>>>s2 = [True, 5, 'smile']                          # s2是一个list

tuple和list的主要区别在于,一旦建立,tuple的各个元素不可再变更,而list的各个元素可以再变更。

>>>s2[1] = 3.0#赋值
>>>print s3[1][2]#引用
>>>>print s1[0:5:2]          # 从下标0到下标4 (下标5不包括在内),每隔2取一个元素 (下标为0,2,4的元素)
>>>print s1[2:0:-1]         # 从下标2到下标1
>>>print s1[:5]             # 从开始到下标4 (下标5的元素 不包括在内)
>>>print s1[2:]             # 从下标2到最后
>>>print s1[-3]             # 序列倒数第三个元素

字符串是元组

>>>str = 'abcdef'
>>>print str[2:4]

2.判断

>>>print 5 in [1,3,5]  

3.流程控制

3.1循环语句

for
for a in [3,4.4,'life']:
    print a#这个循环就是每次从表[3,4.4,'life'] 中取出一个元素(回忆:表是一种序列)
for a in range(10):
    print a**2
while
i = 0
while i < 10:
    print i
    i = i + 1
while会不停地循环执行隶属于它的语句,直到条件为假(False)。
中断循环
  • continue 在循环的某一次执行中,如果遇到continue, 那么跳过这一次执行,进行下一次的操作
  • break 停止执行整个循环
for i in range(10):
    if i == 2: 
        continue
    print i
for i in range(10):
    if i == 2:        
        break
    print i
range()

1、range()

S = 'abcdefghijk'
for i in range(0,len(S),2):
    print S[i]
enumerate()

利用enumerate()函数,可以在每次循环中同时得到下标和元素:一次返回两个

S = 'abcdefghijk'
for (index,char) in enumerate(S):
    print index
    print char

实际上,enumerate()在每次循环中,返回的是一个包含两个元素的定值表(tuple),两个元素分别赋予index和char。

zip()

zip()函数的功能,就是从多个列表中,依次各取出一个元素。每次取出的(来自不同列表的)元素合成一个元组,合并成的元组放入zip()返回的列表中。zip()函数起到了聚合列表的功能。

##聚合列表
ta = [1,2,3]
tb = [9,8,7]
tc = ['a','b','c']
for (a,b,c) in zip(ta,tb,tc):
    print(a,b,c)
##分解聚合后的列表
ta = [1,2,3]
tb = [9,8,7]

# cluster
zipped = zip(ta,tb)
print(zipped)

# decompose
na, nb = zip(*zipped)
print(na, nb)
runfile('E:/Desktop/t1.py', wdir='E:/Desktop')
(1, 9, 'a')
(2, 8, 'b')
(3, 7, 'c')
[(1, 9), (2, 8), (3, 7)]
((1, 2, 3), (9, 8, 7))

每次循环时,从各个序列分别从左到右取出一个元素,合并成一个tuple,然后tuple的元素赋予给a,b,c 。

3.2循环对象

1.什么是循环对象

相对于序列,用循环对象的好处在于:不用在循环还没有开始的时候,就生成好要使用的元素。所使用的元素可以在循环过程中逐次生成。这样,节省了空间,提高了效率,编程更灵活。

环对象是这样一个对象,它包含有一个next()方法 ( __next__() 方法,在python 3x中 ), 这个方法的目的是进行到下一个结果,而在结束一系列结果之后,举出Stop Iteration错误

当一个循环结构(比如for)调用循环对象时,它就会:

  • 每次循环的时候调用next()方法,直到Stop Iteration出现
  • for循环接收到,就知道循环已经结束,停止调用next()

假设我们有一个test.txt的文件:

1234
abcd
efg

python code

#open()返回的实际上是一个循环对象,包含有next()方法。
#而该next()方法每次返回的就是新的一行的内容,到达文件结尾时举出StopIteration。这样,我们相当于手工进行了循环。
>>>f = open('test.txt')

>>>f.next()

>>>f.next()
#自动进行:在这里,for结构自动调用next()方法,将该方法的返回值赋予给line。循环知道出现Stop Iteration的时候结束。
for line in open('test.txt'):
    print line

1234

abcd

efg
2.迭代器

从技术上来说,循环对象和for循环调用之间还有一个中间层,就是要将循环对象转换成迭代器(iterator)。这一转换是通过使用iter()函数实现的。但从逻辑层面上,常常可以忽略这一层,所以循环对象和迭代器常常相互指代对方

3.生成器

生成器(generator)的主要目的是构成一个用户自定义的循环对象。

生成器的编写方法和函数定义类似,只是在return的地方改为yield。生成器中可以有多个yield。当生成器遇到一个yield时,会暂停运行生成器,返回yield后面的值。当再次调用生成器的时候,会从刚才暂停的地方继续运行,直到下一个yield。生成器自身又构成一个循环器,每次循环使用一个yield返回的值。

下面是一个生成器

def gen():
    a = 100
    yield a
    a = a*8
    yield a
    yield 1000
def gen():
    for i in range(4):
        yield i
for i in gen():
    print i
4.表推导

表推导(list comprehension)是快速生成表的方法
表推导的机制实际上是利用循环对象

L = []
for x in range(10):
    L.append(x**2)
#以上产生了表L,但实际上有快捷的写法,也就是表推导的方式:
#这与生成器表达式类似,只不过用的是**中括号**。
L = [x**2 for x in range(10)]    

4.函数

函数最重要的目的是方便我们重复使用相同的一段程序。

4.1函数的定义

首先,我们要定义一个函数, 以说明这个函数的功能

def square_sum(a,b):
    c = a**2 + b**2
    return c
  • return c # 返回c的值,也就是输出的功能。Python的函数允许不返回值,也就是不用return。
  • return可以返回多个值,以逗号分隔。相当于返回一个tuple(定值表

  • return a,b,c # 相当于 return (a,b,c)

2.函数调用和参数传递

a = 1

def change_integer(a):
    a = a + 1
    return a

print change_integer(a)      #注意观察结果
print a      #注意观察结果

b = [1,2,3]

def change_list(b):
    b[0] = b[0] + 1
    return b

print change_list(b)      #注意观察结果
print b      #注意观察结果
  • 第一个例子,我们将一个整数变量传递给函数,函数对它进行操作,但原整数变量a不发生变化。
  • 第二个例子,我们将一个表传递给函数,函数进行操作,原来的表b发生变化。
  • 对于基本数据类型的变量,变量传递给函数后,函数会在内存中复制一个新的变量,从而不影响原来的变量。(我们称此为值传递
  • 但是对于表来说,表传递给函数的是一个指针,指针指向序列在内存中的位置,在函数中对表的操作将在原有内存中进行,从而影响原有变量(我们称此为指针传递

3.函数的参数传递

3.1根据位置传递
def f(a,b,c):
    return a+b+c

print(f(1,2,3))
3.2关键字传递

关键字(keyword)传递是根据每个参数的名字传递参数。关键字并不用遵守位置的对应关系

print(f(c=3,b=2,a=1))

关键字传递可以和位置传递混用。但位置参数要出现在关键字参数之前

print(f(1,c=3,b=2))

参数默认值

def f(a,b,c=10):
    return a+b+c

print(f(3,2))
print(f(3,2,1))
3.3包裹传递

在定义函数时,我们有时候并不知道调用的时候会传递多少个参数。这时候,包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会非常有用
1.包裹位置传递
在func的参数表中,所有的参数被name收集根据位置合并成一个元组(tuple),这就是包裹位置传递;为了提醒Python参数,name是包裹位置传递所用的元组名,在定义func时,在name前加*

def func(*name):
    print type(name)
    print name

func(1,4,6)
func(5,6,7,1,2,3)
#两次调用,尽管参数个数不同,都基于同一个func定义。

包裹关键字传递
与上面一个例子类似,dict是一个字典,收集所有的关键字,传递给函数func。为了提醒Python,参数dict是包裹关键字传递所用的字典,在dict前加 * *

def func(**dict):
    print type(dict)
    print dict

func(a=1,b=9)
func(m=2,n=1,c=11)
#结果
<type 'dict'>
{'a': 1, 'b': 9}
<type 'dict'>
{'c': 11, 'm': 2, 'n': 1}

解包裹
***,也可以在调用的时候使用,即解包裹(unpacking)

  1. tuple

所谓的解包裹,就是在传递tuple时,让tuple的每一个元素对应一个位置参数。在调用func时使用 * ,是为了提醒Python:我想要把args拆成分散的三个元素,分别传递给a,b,c

def func(a,b,c):
    print a,b,c

args = (1,3,4)
func(*args)
#
1 3 4

2.dict

dict = {'a':1,'b':2,'c':3}
func(**dict)#在传递词典dict时,让词典的每个键值对作为一个关键字传递给func
>>>123

3.4函数对象

1、lambda函数

lambda生成一个函数对象。该函数参数为x,y,返回值为x+y。函数对象赋给func。func的调用与正常函数无异。

func = lambda x,y: x + y
print func(3,4)
#一样
def func(x, y):
    return x + y
2.函数作为参数传递
def test(f, a, b):
    print 'test'
    print f(a, b)

test(func, 3, 5)
##更灵活的写法
test((lambda x,y: x**2 + y), 6, 9)

test函数的第一个参数f就是一个函数对象。将func传递给f,test中的f()就拥有了func()的功能

3.map()函数

它的第一个参数是一个函数对象。

#1
re = map((lambda x: x+3),[1,3,5,6])
#2
re = map((lambda x,y: x+y),[1,2,3],[6,7,9])
map()将每次从两个表中分别取出一个元素,带入lambda所定义的函数。
  • map()有两个参数,一个是lambda所定义的函数对象,一个是包含有多个元素的表。
  • map()的功能是将函数对象依次作用于表的每一个元素
  • 如果作为参数的函数对象有多个参数,可使用下面的方式,向map()传递函数参数的多个参数#2

    5.reduce()函数

    reduce函数的第一个参数也是函数,但有一个要求,就是这个函数自身能接收两个参数。reduce可以累进地将函数作用于各个参数

print reduce((lambda x,y: x+y),[1,2,5,7,9])

上面例子,相当于(((1+2)+5)+7)+9

4.面向对象

在人类认知中,会根据属性相近把东西归类,并且给类别命名。比如说,鸟类的共同属性是有羽毛,通过产卵生育后代。任何一只特别的鸟(对象)都在鸟类的原型基础上的。

1.相近对象–类

class Bird(object):
    have_feather = True
    way_of_reproduction  = 'egg'
summer = Bird()
print summer.way_of_reproduction

通过第一句创建对象,并说明summer是类别鸟中的一个对象,summer就有了鸟的类属性,对属性的引用是通过 对象.属性(object.attribute) 的形式实现的。

2.动作

我们在通过属性识别类别的时候,有时根据这个东西能做什么事情来区分类别。比如说,鸟会移动。这样,鸟就和房屋的类别区分开了。这些动作会带来一定的结果,比如移动导致位置的变化。
这样的一些“行为”属性为方法(method)。Python中通过在类的内部定义函数,来说明方法

这里写代码class Bird(object):
    have_feather = True
    way_of_reproduction = 'egg'
    def move(self, dx, dy):
        position = [0,0]
        position[0] = position[0] + dx
        position[1] = position[1] + dy
        return position

summer = Bird()
print 'after move:',summer.move(5,8)
(它的参数中有一个self,它是为了方便我们引用对象自身。方法的第一个参数必须是self,无论是否用到。有关self的内容稍后介绍)

另外两个参数,dx, dy表示在x、y两个方向移动的距离。move方法会最终返回运算过的position。

在最后调用move方法的时候,我们只传递了dx和dy两个参数,不需要传递self参数(因为self只是为了内部使用)。

3.子类

类别本身还可以进一步细分成子类。比如说,鸟类可以进一步分成鸡,大雁,黄鹂。

在OOP中,我们通过继承(inheritance)来表达上述概念。

class Chicken(Bird):
    way_of_move = 'walk'
    possible_in_KFC = True

class Oriole(Bird):
    way_of_move = 'fly'
    possible_in_KFC = False

summer = Chicken()
print summer.have_feather
print summer.move(5,8)

定义的鸡(Chicken)类的,增加了两个属性:移动方式(way_of_move),可能在KFC找到(possible_in_KFC)。

在类定义时,括号里为了Bird。这说明,Chicken是属于鸟类(Bird)的一个子类,即Chicken继承自Bird。自然而然,Bird就是Chicken的父类。Chicken将享有Bird的所有属性。尽管我只声明了summer是鸡类,它通过继承享有了父类的属性(无论是变量属性have_feather还是方法属性move)

没有父类:(object)

4.拓展

4.1调用类的其它信息

只能通过self,调用类属性(类内部函数)

class Human(object):
    laugh = 'hahahaha'
    def show_laugh(self):    
        print self.laugh 
        #通过self.laugh,调用了该属性的值

    def laugh_100th(self):
        for i in range(100):
            self.show_laugh()

li_lei = Human()          
li_lei.laugh_100th()

对象中对类属性进行赋值的时候,实际上会在对象定义的作用域中添加一个属性(如果还不存在的话),并不会影响到相应类中定义的同名类属性。但如果是修改类属性的内容(比如类属性是个字典,修改字典内容)时会影响到所有对象实例,因为这个类属性的内容是共享的。

4.2__init__() 方法

创建对象时,Python会自动调用这个方法。这个过程也叫初始化。

class happyBird(Bird):
    def __init__(self,more_words):
        print 'We are happy birds.',more_words

summer = happyBird('Happy,Happy!')
4.3类的参数–对象的性质(都会有的,但值可能不同)
class Human(object):
    def __init__(self, input_gender):
        self.gender = input_gender
    def printGender(self):
        print self.gender

li_lei = Human('male') # 这里,'male'作为参数传递给__init__()方法的input_gender变量。
print li_lei.gender   #这一行结果与下一行对比
li_lei.printGender()   #这一行结果与上一行对比。。一样额

dict

'clear',
 'copy',
 'fromkeys',
 'get',
 'has_key',
 'items',
 'iteritems',
 'iterkeys',
 'itervalues',
 'keys',
 'pop',
 'popitem',
 'setdefault',
 'update',
 'values',
 'viewitems',
 'viewkeys',
 'viewvalues']

词典 (dictionary)。与列表相似,词典也可以储存多个元素。这种储存多个元素的对象称为容器(container)。

基本

1.创建

>>>dic = {'tom':11, 'sam':57,'lily':100}

>>>print type(dic)

2.引用
词典的元素没有顺序。你不能通过下标引用元素。词典是通过键来引用。

>>>print dic['tom']

>>>dic['tom'] = 30

>>>print dic

增添

>>>dic['lilei'] = 99

>>>print dic

循环调用

dic = {'lilei': 90, 'lily': 100, 'sam': 57, 'tom': 90}
for key in dic:
    print dic[key]

调用其它内置函数

>>>print dic.keys()           # 返回dic所有的键

>>>print dic.values()         # 返回dic所有的值

>>>print dic.items()          # 返回dic所有的元素(键值对)

>>>dic.clear()                # 清空dic,dict变为{}

>>>del dic['tom']             # 删除 dic 的‘tom’元素

5.文本文件的输入输出

我们打开一个文件,并使用一个对象来表示该文件:

1、创建文件对象

对象名 = open(文件名,模式)
  • r 打开只读文件,该文件必须存在
  • r+ 打开可读写的文件,该文件必须存在。
  • w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
  • w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
  • a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留
  • a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。

2、文件对象的方法

读取

content = f.read(N)          # 读取N bytes的数据

content = f.readline()       # 读取一行

content = f.readlines()      # 读取所有行,储存在列表中,每个元素是一行。

写入

f.write('I like apple!\n')      # 将'I like apple'写入文件并换行
f.close()   # 不要忘记关闭文件

6.模块

1.引入方式

import a
import a as b             # 引入模块a,并将模块a重命名为b

from a import function1   # 从模块a中引入function1对象。调用a中对象时,我们不用再说明模块,即直接使用function1,而不是a.function1。

from a import *           # 从模块a中引入所有对象。调用a中对象时,我们不用再说明模块,即直接使用对象,而不是a.对象。

2.搜索路径

!!!important
Python会在以下路径中搜索它想要寻找的模块:
-程序所在的文件夹
-操作系统环境变量PYTHONPATH所包含的路径
-标准库的安装路径

如果你有自定义的模块,或者下载的模块,可以根据情况放在相应的路径,以便Python可以找到。

模块包(很多模块)

可以将功能相似的模块放在同一个文件夹(比如说this_dir)中,构成一个模块包。通过

import this_dir.module

引入this_dir**文件夹中的module模块**。

该文件夹中必须包含一个 __init__.py 的文件,提醒Python,该文件夹为一个模块包。__init__.py 可以是一个空文

7.错误处理

re = iter(range(5))

try:
    for i in range(100):
        print re.next()
except StopIteration:
    print 'here is end ',i

print 'HaHaHaHa'
try:
    ...
except exception1:
    ...
except exception2:
    ...
except:
    ...
else:
    ...
finally:
    ...
  • try->异常->except->finally
  • try->无异常->else->finally

    如果try中有异常发生时,将执行异常的归属,执行except。异常层层比较,看是否是exception1, exception2…,直到找到其归属,执行相应的except中的语句。如果except后面没有任何参数,那么表示所有的exception都交给这段程序处理

如果无法将异常交给合适的对象,异常将继续向上层抛出,直到被捕捉或者造成主程序报错:

def test_func():
    try:
        m = 1/0
    except NameError:
        print("Catch NameError in the sub-function")

try:
    test_func()
except ZeroDivisionError:#输不出结果,但问题也不是nameerror
    print("Catch error in the main program")

raise error

raise StopIteration()
print 'Lalala'
raise StopIteration
print 'Hahaha'

8.动态类型

对象是储存在内存中的实体。但我们并不能直接接触到该对象。我们在程序中写的对象名,只是指向这一对象的引用(reference)
引用和对象分离,是动态类型的核心。引用可以随时指向一个新的对象:

a = 3
a = 'at'
#1
L1 = [1,2,3]
L2 = L1
L1 = 1
#2
L1 = [1,2,3]
L2 = L1
L1[0] = 10

#1即使是多个引用指向同一个对象,如果一个引用值发生变化,那么实际上是让这个引用指向一个新的引用,并不影响其他的引用的指向

#2:

  • L1,L2的指向没有发生变化,依然指向那个表
  • 表实际上是包含了多个引用的对象(每个引用是一个元素,比如L1[0],L1[1]…, 每个引用指向一个对象,比如1,2,3)
  • 而L1[0] = 10这一赋值操作,并不是改变L1的指向,而是对L1[0], 也就是表对象的一部份(一个元素),进行操作,L1,L2都指向10。

    函数参数传递

    函数的参数传递,本质上传递的是引用

#值传递
def f(x):
    x = 100
    print x

a = 1
f(a)
print a
#指针
def f(x):
    x[0] = 100
    print x

a = [1,2,3]
f(a)
print a
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值