运算符
算术运算符
比较运算符
赋值运算符
位运算符
逻辑运算符
成员运算符
身份运算符
运算符优先级
具有相同优先级的运算符将从左至右的方式依次进行。用小括号()可以改变运算顺序。
变量
变量在使用前必须先”定义”(即赋予变量一个值),否则会报错:
nameTraceback(mostrecentcalllast):Filestdin,line1,inmoduleNameError:namenameisnotdefined
数据类型
布尔(bool)
只有True和False两个值,表示真或假。
数字(number)
整型(int)
整数值,可正数亦可复数,无小数。3.x整型是没有限制大小的,可以当作Long类型使用,所以3.x没有2.x的Long类型。
浮点型(float)
浮点型由整数部分与小数部分组成,浮点型也可以使用科学计数法表示(2.5e2=2.5x10^2=)
复数(
continue语句用在while和for循环中,continue语句用来告诉Python跳过当前循环的剩余语句,然后继续进行下一轮循环。continue语句跳出本次循环,而break跳出整个循环。
pass是空语句,是为了保持程序结构的完整性。pass不做任何事情,一般用做占位语句。
迭代器
迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。迭代器有两个基本的方法:iter()和next()。字符串,列表或元组对象都可用于创建迭代器。
迭代器可以被for循环进行遍历:
li=[1,2,3]it=iter(li)forvalinit:print(val)
迭代器也可以用next()函数访问下一个元素值:
importsysli=[1,2,3,4]it=iter(li)whileTrue:try:print(next(it))exceptStopIteration:sys.exit()
生成器
在Python中,使用了yield的函数被称为生成器(generator)。跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。在调用生成器运行的过程中,每次遇到yield时函数会暂停并保存当前所有的运行信息,返回yield的值,并在下一次执行next()方法时从当前位置继续运行。调用一个生成器函数,返回的是一个迭代器对象。
importsysdeffibonacci(n):#生成器函数-斐波那契a,b,counter=0,1,0whileTrue:if(countern):returnyieldaa,b=b,a+bcounter+=1f=fibonacci(10)#f是一个迭代器,由生成器返回生成whileTrue:try:print(next(f))exceptStopIteration:sys.exit()
函数
自定义函数
函数(Functions)是指可重复使用的程序片段。它们允许你为某个代码块赋予名字,允许你通过这一特殊的名字在你的程序任何地方来运行代码块,并可重复任何次数。这就是所谓的调用(Calling)函数。
函数代码块以def关键词开头,后接函数标识符名称和圆括号()。任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。函数内容以冒号起始,并且缩进。return[表达式]结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回None。
return可以返回多个值,此时返回的数据未元组类型。定义参数时,带默认值的参数必须在无默认值参数的后面。
def函数名(参数列表):函数体
参数传递
在Python中,类型属于对象,变量是没有类型的:
a=[1,2,3]a=Runoob
以上代码中,[1,2,3]是List类型,”Runoob”是String类型,而变量a是没有类型,她仅仅是一个对象的引用(一个指针),可以是指向List类型对象,也可以是指向String类型对象。
可更改与不可更改对象
在Python中,字符串,数字和元组是不可更改的对象,而列表、字典等则是可以修改的对象。
不可变类型:变量赋值a=5后再赋值a=10,这里实际是新生成一个int值对象10,再让a指向它,而5被丢弃,不是改变a的值,相当于新生成了a。可变类型:变量赋值la=[1,2,3,4]后再赋值la[2]=5则是将listla的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。
Python函数的参数传递:
不可变类型:类似c++的值传递,如整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在fun(a)内部修改a的值,只是修改另一个复制的对象,不会影响a本身。可变类型:类似c++的引用传递,如列表,字典。如fun(la),则是将la真正的传过去,修改后fun外部的la也会受影响
Python中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
参数
必需参数
必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。
关键字参数
关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为Python解释器能够用参数名匹配参数值。
defprint_info(name,age):打印任何传入的字符串print(名字:,name)print(年龄:,age)returnprint_info(age=50,name=john)
默认参数
调用函数时,如果没有传递参数,则会使用默认参数。
defprint_info(name,age=35):print(名字:,name)print(年龄:,age)returnprint_info(age=50,name=john)print(------------------------)print_info(name=john)
不定长参数
加了星号*的参数会以元组的形式导入,存放所有未命名的变量参数。如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。
defprint_info(arg1,*vartuple):print(输出:)print(arg1)forvarinvartuple:print(var)returnprint_info(10)print_info(70,60,50)
加了两个星号**的参数会以字典的形式导入。变量名为键,变量值为字典元素值。
defprint_info(arg1,**vardict):print(输出:)print(arg1)print(vardict)print_info(1,a=2,b=3)
匿名函数
Python使用lambda来创建匿名函数。
所谓匿名,意即不再使用def语句这样标准的形式定义一个函数。
lambda只是一个表达式,函数体比def简单很多。lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。lambda函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
#语法格式lambda[arg1[,arg2,.....argn]]:expression
变量作用域
L(Local)局部作用域E(Enclosing)闭包函数外的函数中G(Global)全局作用域B(Built-in)内建作用域
以L–E–G–B的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。
Python中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问。
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。
当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字。
num=1deffun1():globalnum#需要使用global关键字声明print(num)num=print(num)fun1()
如果要修改嵌套作用域(enclosing作用域,外层非全局作用域)中的变量则需要nonlocal关键字。
defouter():num=10definner():nonlocalnum#nonlocal关键字声明num=print(num)inner()print(num)outer()
模块
编写模块有很多种方法,其中最简单的一种便是创建一个包含函数与变量、以.py为后缀的文件。
另一种方法是使用撰写Python解释器本身的本地语言来编写模块。举例来说,你可以使用C语言来撰写Python模块,并且在编译后,你可以通过标准Python解释器在你的Python代码中使用它们。
模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。这也是使用Python标准库的方法。
当解释器遇到import语句,如果模块在当前的搜索路径就会被导入。
搜索路径是一个解释器会先进行搜索的所有目录的列表。如想要导入模块,需要把命令放在脚本的顶端。一个模块只会被导入一次,这样可以防止导入模块被一遍又一遍地执行。
搜索路径被存储在sys模块中的path变量。当前目录指的是程序启动的目录。
导入模块
导入模块:
importmodule1[,module2[,...moduleN]]
从模块中导入一个指定的部分到当前命名空间中:
frommodnameimportname1[,name2[,...nameN]]
把一个模块的所有内容全都导入到当前的命名空间:
frommodnameimport*
__name__属性
每个模块都有一个__name__属性,当其值是__main__时,表明该模块自身在运行,否则是被引入。
一个模块被另一个程序第一次引入时,其主程序将运行。如果我们想在模块被引入时,模块中的某一程序块不执行,我们可以用__name__属性来使该程序块仅在该模块自身运行时执行。
if__name__==__main__:print(程序自身在运行)else:print(我来自另一模块)
dir函数
内置的函数dir()可以找到模块内定义的所有名称。以一个字符串列表的形式返回。
如果没有给定参数,那么dir()函数会罗列出当前定义的所有名称。
在Python中万物皆对象,int、str、float、list、tuple等内置数据类型其实也是类,也可以用
dir(int)查看int包含的所有方法。也可以使用help(int)查看int类的帮助信息。
包
包是一种管理Python模块命名空间的形式,采用”点模块名称”。
比如一个模块的名称是A.B,那么他表示一个包A中的子模块B。
就好像使用模块的时候,你不用担心不同模块之间的全局变量相互影响一样,采用点模块名称这种形式也不用担心不同库之间的模块重名的情况。
在导入一个包的时候,Python会根据sys.path中的目录来寻找这个包中包含的子目录。
目录只有包含一个叫做__init__.py的文件才会被认作是一个包,主要是为了避免一些滥俗的名字(比如叫做string)不小心的影响搜索路径中的有效模块。
最简单的情况,放一个空的__init__.py文件就可以了。当然这个文件中也可以包含一些初始化代码或者为__all__
变量赋值。
第三方模块
easy_install和pip都是用来下载安装Python一个公共资源库PyPI的相关资源包的,pip是easy_install的改进版,提供更好的提示信息,删除package等功能。老版本的python中只有easy_install,没有pip。easy_install打包和发布Python包,pip是包管理。
easy_install的用法:
安装一个包easy_install包名easy_install包名==包的版本号升级一个包easy_install-U包名=包的版本号
pip的用法:
安装一个包pipinstall包名pipinstall包名==包的版本号升级一个包(如果不提供version号,升级到最新版本)pipinstall—upgrade包名=包的版本号删除一个包
pipuninstall包名
已安装包列表piplist
面向对象
类与对象是面向对象编程的两个主要方面。一个类(Class)能够创建一种新的类型(Type),其中对象(Object)就是类的实例(Instance)。可以这样来类比:你可以拥有类型int的变量,也就是说存储整数的变量是int类的实例(对象)。
类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。方法:类中定义的函数。类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。实例变量:定义在方法中的变量,只作用于当前实例的类。继承:即一个派生类(derivedclass)继承基类(baseclass)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟”是一个(is-a)”关系(例图,Dog是一个Animal)。实例化:创建一个类的实例,类的具体对象。对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。
对象可以包含任意数量和类型的数据。
self
self表示的是当前实例,代表当前对象的地址。类由self.__class__表示。
self不是关键字,其他名称也可以替代,但self是个通用的标准名称。
类
类由class关键字来创建。类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。
对象方法
方法由def关键字定义,与函数不同的是,方法必须包含参数
self,且为第一个参数,
self代表的是本类的实例。
类方法
装饰器
classmethod可以将方法标识为类方法。类方法的第一个参数必须为cls,而不再是self。静态方法
装饰器
staticmethod可以将方法标识为静态方法。静态方法的第一个参数不再指定,也就不需要self或cls。__init__方法
__init__方法即构造方法,会在类的对象被实例化时先运行,可以将初始化的操作放置到该方法中。如果重写了__init__,实例化子类就不会调用父类已经定义的__init__。
变量
类变量(ClassVariable)是共享的(Shared)——它们可以被属于该类的所有实例访问。该类变量只拥有一个副本,当任何一个对象对类变量作出改变时,发生的变动将在其它所有实例中都会得到体现。
对象变量(Objectvariable)由类的每一个独立的对象或实例所拥有。在这种情况下,每个对象都拥有属于它自己的字段的副本,也就是说,它们不会被共享,也不会以任何方式与其它不同实例中的相同名称的字段产生关联。
在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__name__、__score__这样的变量名。
访问控制
私有属性__private_attr:两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。私有方法__private_method:两个下划线开头,声明该方法为私有方法,只能在类的内部调用,不能在类地外部调用。
我们还认为约定,一个下划线开头的属性或方法为受保护的。比如,_protected_attr、_protected_method。
继承
类可以继承,并且支持继承多个父类。在定义类时,类名后的括号中指定要继承的父类,多个父类之间用逗号分隔。
子类的实例可以完全访问所继承所有父类的非私有属性和方法。
若是父类中有相同的方法名,而在子类使用时未指定,Python从左至右搜索,即方法在子类中未找到时,从左到右查找父类中是否包含方法。
方法重写
子类的方法可以重写父类的方法。重写的方法参数不强制要求保持一致,不过合理的设计都应该保持一致。super()函数可以调用父类的一个方法,以多继承问题。
类的专有方法:
__init__:构造函数,在生成对象时调用
__del__:析构函数,释放对象时使用
__repr__:打印,转换
__setitem__:按照索引赋值
__getitem__:按照索引获取值
__len__:获得长度
__cmp__:比较运算
__call__:函数调用
__add__:加运算
__sub__:减运算
__mul__:乘运算
__div__:除运算
__mod__:求余运算
__pow__:乘方
类的专有方法也支持重载。
实例
classPerson:人员信息#姓名(共有属性)name=#年龄(共有属性)age=0def__init__(self,name=,age=0):self.name=nameself.age=age#重载专有方法:__str__def__str__(self):return这里重载了__str__专有方法,+str({name:self.name,age:self.age})defset_age(self,age):self.age=ageclassAccount:账户信息#账户余额(私有属性)__balance=0#所有账户总额__total_balance=0#获取账户余额#self必须是方法的第一个参数defbalance(self):returnself.__balance#增加账户余额defbalance_add(self,cost):#self访问的是本实例self.__balance+=cost#self.__class__可以访问类self.__class__.__total_balance+=cost#类方法(用
classmethod标识,第一个参数为cls)classmethoddeftotal_balance(cls):returncls.__total_balance#静态方法(用staticmethod标识,不需要类参数或实例参数)staticmethoddefexchange(a,b):returnb,aclassTeacher(Person,Account):教师#班级名称_class_name=def__init__(self,name):#第一种重载父类__init__()构造方法#super(子类,self).__init__(参数1,参数2,....)super(Teacher,self).__init__(name)defget_info(self):#以字典的形式返回个人信息return{name:self.name,#此处访问的是父类Person的属性值age:self.age,class_name:self._class_name,balance:self.balance(),#此处调用的是子类重载过的方法}#方法重载defbalance(self):#Account.__balance为私有属性,子类无法访问,所以父类提供方法进行访问returnAccount.balance(self)*1.1classStudent(Person,Account):学生_teacher_name=def__init__(self,name,age=18):#第二种重载父类__init__()构造方法#父类名称.__init__(self,参数1,参数2,...)Person.__init__(self,name,age)defget_info(self):#以字典的形式返回个人信息return{name:self.name,#此处访问的是父类Person的属性值age:self.age,teacher_name:self._teacher_name,balance:self.balance(),}#教师Johnjohn=Teacher(John)john.balance_add(20)john.set_age(36)#子类的实例可以直接调用父类的方法print(Johnsinfo:,john.get_info())#学生Marymary=Student(Mary,18)mary.balance_add(18)print(Marysinfo:,mary.get_info())#学生Fakefake=Student(Fake)fake.balance_add(30)print(Fakesinfo,fake.get_info())#三种不同的方式调用静态方法print(john.exchange(a,b):,john.exchange(a,b))print(Teacher.exchange(1,2),Teacher.exchange(1,2))print(Account.exchange(10,20):,Account.exchange(10,20))#类方法、类属性print(Account.total_balance():,Account.total_balance())print(Teacher.total_balance():,Teacher.total_balance())print(Student.total_balance():,Student.total_balance())#重载专有方法print(fake)输出:
Johnsinfo:{name:John,age:36,class_name:,balance:22.0}Marysinfo:{name:Mary,age:18,teacher_name:,balance:18}Fakesinfo{name:Fake,age:18,teacher_name:,balance:30}john.exchange(a,b):(b,a)Teacher.exchange(1,2)(2,1)Account.exchange(10,20):(20,10)Account.total_balance():0Teacher.total_balance():20Student.total_balance():48这里重载了__str__专有方法,{name:Fake,age:18}