python学习笔记

学习笔记:廖雪峰的官方网站https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000

1 输入和输出

print(“hello”, “world”) 多个字符串依次打印,遇到逗号会输出空格; name=input(‘please enter your name’)让用户从电脑输入一些字符,返回str; # 是注释;

每一行都是一个语句,语句以冒号:结尾时缩进的语句为代码块,一般缩进为4个空格; Python是大小写敏感的。

2 数据类型

(1) 整数:1,-9,300; 

(2) 浮点数:1.23,3.14,-9.01;

(3) 字符串:单引号或双引号成对括起来的文本,三引号’’’…’’’表示多行内容; 转义符\来转义字符;r’\\n\\’表示引号内部的字符串默认不转义;

字符串是不可变对象,调用对象自身的任意方法,也不会改变该对象自身的内容。相反,这些方法会创建新的对象并返回,这样,就保证了不可变对象本身永远是不可变的。

a = 'abc'
b = a.replace('a', 'A')
b='Abc'

b是新创建的, a不变。

(4) 布尔值:True, False。非零为真。 int(‘4.0’)强制转换,float(),str(),bool()强制转换

(5) list: 是可变的有序表,可以随时添加和删除其中的元素, list里面的元素的数据类型可以不同, list元素可以是另一个list。

s = ['python', 'java', ['asp', 'php'],'scheme']
s[2][1]=’php’

a=[1,2,’g’]len()获取长度,索引从左到右是从0开始,反向是从-1开始。

a.append(‘a’)追加元素到末尾 a.insert(2, 4)插入元素到指定位置 a.pop() 删除末尾元素; a.pop(3) 删除指定位置的元素 直接赋值可以替换元素:a[1]=’sun’

(6) tuple一旦初始化就不能修改,只有1个元素的tuple定义时必须加一个逗号,t = ('a', 'b', ['A', 'B'])   t[2][0] = 'X'

tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。但指向的这个list本身是可变的。

(7) dict: 全称dictionary,使用键-值(key-value)存储,具有极快的查找速度,需要占用大量的内存,内存浪费多。

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

d['Adam'] = 67, 加一个键值对 判断key存在:‘a’ in d 或者 d.get(‘a’,-1) 删除key: d.pop(‘Adam’)

dict内部存放的顺序和key放入的顺序是没有关系的。dict的key必须是不可变对象。

(8) set : set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。

重复元素在set中自动被过滤, 要创建一个set,需要提供一个list作为输入集合:

s = set([1, 2, 3])

s.add(4) 添加元素s.remove(4)删除元素 set可以看成数学意义上的无序无重复元素的集合,因此,两个set可以做数学意义上的交集&、并集|等操作;

3 变量

变量本身类型不固定,是动态语言即a=1或a=’w’,定义变量时不需要指定变量类型,可以把任意数值类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量。

a=’w’执行时Python解释器做了两件事: (1)内存中创建’w‘字符串; (2)创建名为a的变量,并指向’w’。

4 格式化

常见的占位符有:%d整数,%f浮点数,%s字符串,%x十六进制整数;%s会把任何数据类型转换为字符串;

格式化整数和浮点数还可以指定是否补0和整数与小数的位数:’%2d,%02d’%(3,1) 字符串里面的%是一个普通字符就需要转义,用%%来表示一个%;

5 条件判断与循环

if:   elif:   else: 
for i in range(101):  
while n>0:

range(101)是从零开始小于100的整数序列,在 循环中,break语句可以提前退出循环。

在循环过程中,也可以通过continue语句,跳过当前的这次循环,直接开始下一次循环。 Ctrl+C退出程序,或者强制结束Python进程。

for key in d   for value in d.values()   for k, v in d.items()

for循环,作用于一个可迭代对象。通过collections模块的Iterable类型判断一个对象是可迭代对象

from collections import Iterable
isinstance('abc', Iterable)

Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身。

for循环里,可同时引用两个变量。

6 函数

函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”。

函数名其实就是指向函数的变量,也可把函数作为参数传入,这样的函数称为高阶函数

在Python中,定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。

pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。

Python的函数返回多值其实就是返回一个tuple, 而多个变量可以同时接收一个tuple,按位置赋给对应的值。

def mine(x,y):
    if not isinstance(x, (int, float)): #数据类型检查
        print('ERROR')
    else:
        n=str(x)
        m=y*2
    return m,n

7 函数的参数

(1) 位置参数:传入的值按照位置顺序传入

(2) 默认参数:默认参数必须指向不变对象

(3) 可变参数:传入的参数个数是可变的 def calc(*numbers): numbers可以把多个参数,作为tuple传入;如有a=(1,2,3), calc(*a)

(4) 关键字参数:而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict

def person(name, age, **kw):
person('Bob', 35, city='Beijing')

也可以先组装出一个dict,然后,把该dict转换为关键字参数传进去: extra = {'city': 'B', 'job': 'E'} person('Jack', 24, **extra)

(5) 命名关键字参数:如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。

def person(name, age, *, city, job): 和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符**后面的参数被视为命名关键字参数。

命名关键字参数可以有缺省值,从而简化调用。 如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了。

参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

8 高级特性

(1) 切片,L[a:b:c],包含a但不包含b, c是间隔。

(2) 列表生成式,把要生成的元素x * x放到前面,后面跟for循环, 可以加上if判断, 还可以使用两层循环 [x*x for x in range(1,10) if x%2==0]

(3) generator,循环的过程中不断推算出后续的元素 g = (x * x for x in range(10))

通过next()函数获得generator的下一个返回值generator也是可迭代对象,可以用for循环。

如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。

函数是顺序执行,遇到return语句或者最后一行函数语句就返回。

而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

直到最后抛出StopIteration错误表示无法继续返回下一个值了。

(4) Iterator, 可以被next()函数调用并不断返回下一个值的对象称为迭代器 可以使用isinstance()判断一个对象是否是Iterator

from collections import Iterator
isinstance((x for x in range(10)), Iterator)

凡是可作用于for循环的对象都是Iterable类型; 凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象

9 高阶函数

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

(2) reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算。from functools import reduce

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

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

(4) sorted()排序sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)

10 函数式编程

(1) 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。

调用lazy_sum()返回函数,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,称为闭包。

返回的函数并没有立刻执行,f=lazy_sum(1,2,3) 调用了 f()函数才执行。

返回函数不要引用任何循环变量,或者后续会发生变化的变量。

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

def lazy_sum(*args):
    def sum():
        ax=0
        for n in args:
            ax=ax+n
        return ax
    return sum

(2) 匿名函数, 关键字lambda表示匿名函数,冒号前面的x表示函数参数, 冒号后面是表达式。lambda x: x * x

(3) 装饰器

(4) 偏函数,当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。

11 模块

每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。

__init__.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块。

类似__xxx__这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的__author__,__name__就是特殊变量。

类似_xxx__xxx这样的函数或变量就是非公开的(private),不应该被直接引用,比如_abc,__abc等;

12 类

(1)由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。

通过定义一个特殊的__init__方法。__init__方法的第一个参数永远是self,表示创建的实例本身

因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。

方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;

和静态语言不同,Python允许对实例变量绑定任何属性如bart.age

class Student(object):

    def __init__(self, name, score):
        self.name = name
        self.score = score

    def print_score(self):
        print('%s: %s' % (self.name, self.score))
bart = Student('Bart Simpson', 59)
bart.age=12

(2)如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__

在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private)self.__name=name,外部代码要获取name, 可以给Student类增加方法.

(3)继承可以把父类的所有功能都直接拿过来,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写。

(4)isinstance()判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上。isinstance([1, 2, 3], (list, tuple) ;

dir()函数获得一个对象的所有属性方法;

getattr()、setattr()以及hasattr(),可以直接操作一个对象的属性或方法;getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404

(5)类属性,直接在class中定义属性。相同名称的实例属性将屏蔽掉类属性。

(6)给实例绑定一个方法,

s = Student()
def qage(self,age):
    self.age=age
from types import MethodType
s.age=MethodType(qage,s)
s.age(9)

给类绑定方法,给class绑定方法后,所有实例均可调用 Student.qage=qage

想要限制实例的属性, 在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性. class Student(object):

     __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称

_slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的, 除非在子类中也定义_slots__这样,子类实例允许定义的属性就是自身的_slots__加上父类的`slots_

(7)Python内置的@property装饰器就是负责把一个方法变成属性调用的。

class Student(object):
    @property
    def age(self):
        return self.__age
    @age.setter
    def age(self,value):
        if not isinstance(value,int):
            raise ValueError('wrong')
        self.__age=value    

(8)__str__:print出实例,不但好看,而且容易看出实例内部重要的数据。 直接显示变量调用的不是__str__()而是__repr__()

两者的区别是__str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串,也就是说__repr__()是为调试服务的。__repr__()定义后可直接显示。

class a(object):
    def __init__(self,name):
        self.__name=name
    def __str__(self):
        return 'hello %s'%self.__name
    __repr__=__str__

 
posted @ 2017-10-17 16:20  未闻花开  阅读(548)  评论(0编辑  收藏  举报