Python基础笔记4如何高效学习?

2026-06-10 21:3315阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计3091个文字,预计阅读时间需要13分钟。

Python基础笔记4如何高效学习?

模块是Python代码的集合,一个.py文件即为一个模块。按目录组织模块称为包。优势包括提高代码的可维护性,避免函数名和变量名冲突。+ mycompany

模块

模块是一组Python代码的集合,一个.py文件就称之为一个模块(Module),按目录来组织模块称为包(Package)。优点:提高了代码的可维护性;避免函数名和变量名冲突。

mycompany#包
├─__init__.py#必需,模块名即为包名
├─abc.py#abc模块
└─xyz.py#xyz模块

#多级层次的包结构
mycompany
├─web#mycompany.web模块
│├─__init__.py
│├─utils.py#mycompany.web.utils
│└─www.py
├─__init__.py
├─abc.py
└─utils.py#mycompany.utils

创建模块时不能和Python自带的模块名称冲突(检查模块是否存在用import abc),否则将无法导入系统自带的模块。

1.使用模块

Python模块的标准文件模板,编写一个hello.py模块:

#!/usr/bin/envpython3#让文件直接在Unix上运行
#_*_coding:utf-8_*_#使用utf-8编码

'atestmodule'#模块的文档注释

__author__='JessePeng'#作者变量

importsys#导入sys模块后,变量sys可以访问该模块所有功能

deftest():
args=sys.argv#argv变量用list存储了命令行的所有参数
iflen(args)==1:#第一个参数是.py文件的名称
print('hello,world!')
eliflen(args)==2:
print('hello,%s!'%args[1])
else:
print('toomanyarguments!')

if__name__=='__main__':#这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。
test()

命令行运行:

python3hello.py
python3hello.pyJesse

交互环境运行:

importhello
hello.test()#需要调用test函数

作用域
正常的函数和变量名是公开的(public),可被直接引用,如abc,x123,PI。
特殊变量__xxx__,如__author__,name。
非公开变量或函数(private),不应该被直接引用,如_abc,__abc。

def_private1(name):#私有函数
return'hello,%s'%name

def_private2(name):#私有函数
return'Hi,%s'%name

defgreeting(name):#公有函数
iflen(name)>3:
return_private1(name)
else:
return_private2(name)

上例中调用公有函数greeting()不用关心内部的私有函数细节,这是一种非常有用的代码封装和抽象的方法。
外部不需要引用的函数全部定义成private,只有外部需要引用的函数才定义为public。

2.安装第三方模块

包管理工具pip。Linux上若并存Python3和Python 2,Python3用pip3。

pipinstallPillow

安装常用模块。
使用anaconda,已经内置了许多第三方库。
默认情况下,Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys.path变量中。

若要添加自己的搜索目录,一是通过sys.path添加:

importsys
sys.path.append('/your/pypath')

二是设置环境变量PYTHONPATH.

面向对象编程OOP

面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。
面向对象的程序设计把计算机程序视为一组对象的集合,对象直接接收并处理消息,计算机执行对象间传递的消息。
所有数据类型都可为对象,也可自定义对象数据类型,也就是类(Class)的概念。
举例比较两者
面向过程:

std={'name':'Jesse','score':90}
defprint_score(std):
print('%s:%s'%(std['name'],std['score']))

面向对象:

classStudent(object):
def__init__(self,name,score):
self.name=name#对象Student的name属性
self.score=score#对象Student的score属性

defprint_score(self):#让对象自己把自己的数据打印出来。
print('%s:%s'%(self.name,self.score))

对象的方法(Method):调用对象对应的关联函数。

bart=Student('bart',59)
lisa=Student('lisa',87)
bart.print_score()
lisa.print_score()

面向对象的设计思想是抽象出Class,根据Class创建Instance。
类(Class)是一种抽象概念,如我们定义的Class——Student,指学生这个概念。一个Class既包含数据,又包含操作数据的方法。
实例(Instance)则是一个个具体的Student,如bart和lisa,各个实例拥有的数据都互相独立,互不影响。
数据封装、继承和多态是面向对象的三大特点。

1.类和实例

定义类:
类名通常首字母大写的单词,(object)表该类从哪个类继承下来的。如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。

classStudent(object):
pass

创建实例:
通过类名()实现

bart=Student()
bart#instance
Student#class

#自由给实例变量绑定属性
bart.name='bart'
bart.name

类可以起到模板的作用,创建实例时可通过定义一个特殊的__init__把必须绑定的属性强制加进去。

classStudent(object):
def__init__(self,name,score):
self.name=name
self.score=score

#调用
bart=Student('bart',59)#不用再传入self,不能为空
bart.name
bart.score

__init__方法的第一个参数永远是self,表示创建的实例本身。仍然可以在类的方法中用默认参数、可变参数、关键字参数和命名关键字参数。

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

数据封装
在上面的Student类中,每个实例就拥有各自的name和score数据,没有必要从外面的函数去访问,可以直接在Student类的内部定义访问数据的函数,这样就把“数据”给封装起来了。这些封装数据的函数是和Student类本身是关联起来的,我们称之为类的方法。

classStudent(object):

def__init__(self,name,score):
self.name=name
self.score=score

defprint_score(self):
print('%s:%s'%(self.name,self.score))

#调用
bart.print_score()

封装使得调用很容易,且不用知道内部实现的细节。另一个好处是可以给类增加新的方法。

classStudent(object):
...

defget_grade(self):#新增
ifself.score>=90:
return'A'
elifself.score>=60:
return'B'
else:
return'C'

#调用
lisa=Student('Lisa',99)
print(lisa.name,lisa.get_grade())

2.访问限制

实例的变量名以__开头就是私有变量(private),只有内部可以访问,外部不能访问。确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。

classStudent(object):
def__init__(self,name,score):
self.__name=name
self.__score=score
defprint_score(self):
print('%s:%s'%(self.__name,self.__score))
#调用
bart=Student('bart',59)
bart.__name#error

要想外部再获取name和score,可给类增加新的获取方法:

classStudent(object):
.......
defget_name(self):
returnself.__name
defget_score(self):
returnself.__score

给类再增加允许外部修改score的方法:

defset_score(self,score):
self.__score=score

为什么不直接进行​​bart.score=99​​修改,非要定义一个私有变量的方法?因为这样可以对参数做检查,避免无效的参数:

classStudent(object):
......
defset_score(self,score):
if0<=score<=100:
self.__score=score
else:
raiseValueError('badscore')

​​__xxx__​​​在Python中是特殊变量,不同于私有变量,可直接访问。而​​_name​​​(一个下划线)变量外部也可访问,但尽量将它视为私有变量,不要随意访问。
实例中私有变量外部也是可以强制使用的,但不要这么做:

bart._Student__name#bart

比较一下:

bart.__name='newname'
bart.__name#newname
#外部新设置了一个变量__name,而内部的__name并未改变

bart.get_name()#bart

3.继承和多肽

父类、子类

#父类
classAnimal(object):
defrun(self):
print('animalisrunning')

#子类
classDog(Animal):
pass
classCat(Animal):
pass

子类继承了父类的全部功能。

dog=Dog()
dog.run()#来自父类的run方法:animalisrunning

cat=Cat()
cat.run()

也可对子类增加新的方法:

classDog(Animal):
defrun(self):#新增方法1
print('dogisrunning')
defeat(self):#新增方法2
print('eatingmeat')

当子类和父类存在相同名字的方法时(如上例run方法),子类会覆盖父类,不同子类拥有不同方法,这就是多态。

类其实也是一种数据类型:

Python基础笔记4如何高效学习?

a=list()#a是list类型
b=Animal()#b是Animal类型
c=Dog()#c是Dog类型

#判断变量是否为某种类型:
isinstance(a,list)
isinstance(b,Animal)
isinstance(c,Dog)

isinstance(c,Animal)#True
isinstance(b,Dog)#False

编写一个接受Animal类型变量的函数来理解多态:

defrun_twice(animal):
animal.run()
animal.run()

#以下都是Animal类型
run_twice(Animal())#Animalisrunning/Animalisrunning
run_twice(Cat())#Catisrunning/Catisrunning
run_twice(Dog())#Dogisrunning/Dogisrunning

传入的类型只要是Animal类或子类,就会自动调用实际类型的run()方法,这就是多态的意思。

多态真正的威力:调用方只管调用,不管细节,而当我们新增一种Animal的子类时,只要确保run()方法编写正确,不用管原来的代码是如何调用的。这就是著名的“开闭”原则:对扩展开放:允许新增Animal子类;对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。

继承可以一级一级地继承下来,而任何类最终都可以追溯到根类object。

Python作为动态语言,它的“file-like object“是一种“鸭子类型”,并不要求严格的继承体系。如上不一定需要传入Animal类型,只需要保证传入的对象有一个run()方法就可以了。

classTimer(object):
defrun(self):
print('start...')

4.获取对象信息

type()函数返回对应的Class类型

#基本类型
type(123)
type('str')
type(None)

#指向函数或类的变量
type(abs)
type(a)

type(123)=int#True
type('abc')=type(123)#False

判断一个对象是否为函数:

importtypes
deffn():
pass

type(fn)==types.FunctionType#True
type(abs)==types.BuiltinFunctionType
type(lambdax:x)==types.LambdaType
type((xforxinrange(10)))==types.GeneratorType

isinstance函数

#创建3种类型对象:
a=Animal()
d=Dog()
h=Husky()

#判断:
isinstance(h,Dog)
isinstance(h,Animal)

#type判断的类型也可用isinstance:
isinstance('abc',str)
#判断一个变量是否是某些类型中的一种
isinstance([1,2,3],(list,tuple))
isinstance((1,2,3),(list,tuple))

dir()函数
获得一个对象的所有属性和方法,返回list。

dir("abc")

len()函数内部自动调用该对象的​​__len__()​​方法:

len('abc')
'abc'.__len__()#效果同上

其他都是普通属性或方法,如lower:

'ABC'.lower()#abc

直接操作一个对象的状态:

#定义一个对象
classMyObject(object):
def__init__(self):
self.x=9
defpower(self):
returnself.x*self.x

obj=MyObject()

#测试对象的属性:
hasattr(obj,'x')#True是否有x属性
obj.x#9
hasattr(obj,'y')#False
setattr(obj,'y',19)#设置一个y属性
hasattr(obj,'y')#True
getattr(obj,'y')#19获取y属性
obj.y#19

getattr(obj,'z',404)#获取属性'z',如果不存在,返回默认值404

#获取对象的方法:
hasattr(obj,'power')
getattr(obj,'power')
fn=getattr(obj,'power')
fn#fn指向obj.power
fn()#同obj.power()

一个例子:

defreadImage(fp):
ifhasattr(fp,'read'):
returnreadData(fp)
returnNone

5.实例属性和类属性

根据类创建的实例可以任意绑定属性,方法是通过实例变量或self变量。

类属性直接在class中定义,这个属性虽然归类所有,但类的所有实例都可以访问到。实例属性属于各个实例所有,互不干扰。

classStudent(object):
name='Student'

s=Student()#创建实例s
print(s.name)#Student
print(Student.name)#Student

s.name='Jesse'#给实例绑定name属性
print(s.name)#Jesse实例属性优先级比类属性高
print(Student.name)#Student

dels.name
print(s.name)#Student

从上看出,最好不要对实例属性和类属性使用相同的名字。


作者:Bioinfarmer

若要及时了解动态信息,请关注同名微信公众号:Bioinfarmer。


本文共计3091个文字,预计阅读时间需要13分钟。

Python基础笔记4如何高效学习?

模块是Python代码的集合,一个.py文件即为一个模块。按目录组织模块称为包。优势包括提高代码的可维护性,避免函数名和变量名冲突。+ mycompany

模块

模块是一组Python代码的集合,一个.py文件就称之为一个模块(Module),按目录来组织模块称为包(Package)。优点:提高了代码的可维护性;避免函数名和变量名冲突。

mycompany#包
├─__init__.py#必需,模块名即为包名
├─abc.py#abc模块
└─xyz.py#xyz模块

#多级层次的包结构
mycompany
├─web#mycompany.web模块
│├─__init__.py
│├─utils.py#mycompany.web.utils
│└─www.py
├─__init__.py
├─abc.py
└─utils.py#mycompany.utils

创建模块时不能和Python自带的模块名称冲突(检查模块是否存在用import abc),否则将无法导入系统自带的模块。

1.使用模块

Python模块的标准文件模板,编写一个hello.py模块:

#!/usr/bin/envpython3#让文件直接在Unix上运行
#_*_coding:utf-8_*_#使用utf-8编码

'atestmodule'#模块的文档注释

__author__='JessePeng'#作者变量

importsys#导入sys模块后,变量sys可以访问该模块所有功能

deftest():
args=sys.argv#argv变量用list存储了命令行的所有参数
iflen(args)==1:#第一个参数是.py文件的名称
print('hello,world!')
eliflen(args)==2:
print('hello,%s!'%args[1])
else:
print('toomanyarguments!')

if__name__=='__main__':#这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。
test()

命令行运行:

python3hello.py
python3hello.pyJesse

交互环境运行:

importhello
hello.test()#需要调用test函数

作用域
正常的函数和变量名是公开的(public),可被直接引用,如abc,x123,PI。
特殊变量__xxx__,如__author__,name。
非公开变量或函数(private),不应该被直接引用,如_abc,__abc。

def_private1(name):#私有函数
return'hello,%s'%name

def_private2(name):#私有函数
return'Hi,%s'%name

defgreeting(name):#公有函数
iflen(name)>3:
return_private1(name)
else:
return_private2(name)

上例中调用公有函数greeting()不用关心内部的私有函数细节,这是一种非常有用的代码封装和抽象的方法。
外部不需要引用的函数全部定义成private,只有外部需要引用的函数才定义为public。

2.安装第三方模块

包管理工具pip。Linux上若并存Python3和Python 2,Python3用pip3。

pipinstallPillow

安装常用模块。
使用anaconda,已经内置了许多第三方库。
默认情况下,Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys.path变量中。

若要添加自己的搜索目录,一是通过sys.path添加:

importsys
sys.path.append('/your/pypath')

二是设置环境变量PYTHONPATH.

面向对象编程OOP

面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。
面向对象的程序设计把计算机程序视为一组对象的集合,对象直接接收并处理消息,计算机执行对象间传递的消息。
所有数据类型都可为对象,也可自定义对象数据类型,也就是类(Class)的概念。
举例比较两者
面向过程:

std={'name':'Jesse','score':90}
defprint_score(std):
print('%s:%s'%(std['name'],std['score']))

面向对象:

classStudent(object):
def__init__(self,name,score):
self.name=name#对象Student的name属性
self.score=score#对象Student的score属性

defprint_score(self):#让对象自己把自己的数据打印出来。
print('%s:%s'%(self.name,self.score))

对象的方法(Method):调用对象对应的关联函数。

bart=Student('bart',59)
lisa=Student('lisa',87)
bart.print_score()
lisa.print_score()

面向对象的设计思想是抽象出Class,根据Class创建Instance。
类(Class)是一种抽象概念,如我们定义的Class——Student,指学生这个概念。一个Class既包含数据,又包含操作数据的方法。
实例(Instance)则是一个个具体的Student,如bart和lisa,各个实例拥有的数据都互相独立,互不影响。
数据封装、继承和多态是面向对象的三大特点。

1.类和实例

定义类:
类名通常首字母大写的单词,(object)表该类从哪个类继承下来的。如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。

classStudent(object):
pass

创建实例:
通过类名()实现

bart=Student()
bart#instance
Student#class

#自由给实例变量绑定属性
bart.name='bart'
bart.name

类可以起到模板的作用,创建实例时可通过定义一个特殊的__init__把必须绑定的属性强制加进去。

classStudent(object):
def__init__(self,name,score):
self.name=name
self.score=score

#调用
bart=Student('bart',59)#不用再传入self,不能为空
bart.name
bart.score

__init__方法的第一个参数永远是self,表示创建的实例本身。仍然可以在类的方法中用默认参数、可变参数、关键字参数和命名关键字参数。

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

数据封装
在上面的Student类中,每个实例就拥有各自的name和score数据,没有必要从外面的函数去访问,可以直接在Student类的内部定义访问数据的函数,这样就把“数据”给封装起来了。这些封装数据的函数是和Student类本身是关联起来的,我们称之为类的方法。

classStudent(object):

def__init__(self,name,score):
self.name=name
self.score=score

defprint_score(self):
print('%s:%s'%(self.name,self.score))

#调用
bart.print_score()

封装使得调用很容易,且不用知道内部实现的细节。另一个好处是可以给类增加新的方法。

classStudent(object):
...

defget_grade(self):#新增
ifself.score>=90:
return'A'
elifself.score>=60:
return'B'
else:
return'C'

#调用
lisa=Student('Lisa',99)
print(lisa.name,lisa.get_grade())

2.访问限制

实例的变量名以__开头就是私有变量(private),只有内部可以访问,外部不能访问。确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。

classStudent(object):
def__init__(self,name,score):
self.__name=name
self.__score=score
defprint_score(self):
print('%s:%s'%(self.__name,self.__score))
#调用
bart=Student('bart',59)
bart.__name#error

要想外部再获取name和score,可给类增加新的获取方法:

classStudent(object):
.......
defget_name(self):
returnself.__name
defget_score(self):
returnself.__score

给类再增加允许外部修改score的方法:

defset_score(self,score):
self.__score=score

为什么不直接进行​​bart.score=99​​修改,非要定义一个私有变量的方法?因为这样可以对参数做检查,避免无效的参数:

classStudent(object):
......
defset_score(self,score):
if0<=score<=100:
self.__score=score
else:
raiseValueError('badscore')

​​__xxx__​​​在Python中是特殊变量,不同于私有变量,可直接访问。而​​_name​​​(一个下划线)变量外部也可访问,但尽量将它视为私有变量,不要随意访问。
实例中私有变量外部也是可以强制使用的,但不要这么做:

bart._Student__name#bart

比较一下:

bart.__name='newname'
bart.__name#newname
#外部新设置了一个变量__name,而内部的__name并未改变

bart.get_name()#bart

3.继承和多肽

父类、子类

#父类
classAnimal(object):
defrun(self):
print('animalisrunning')

#子类
classDog(Animal):
pass
classCat(Animal):
pass

子类继承了父类的全部功能。

dog=Dog()
dog.run()#来自父类的run方法:animalisrunning

cat=Cat()
cat.run()

也可对子类增加新的方法:

classDog(Animal):
defrun(self):#新增方法1
print('dogisrunning')
defeat(self):#新增方法2
print('eatingmeat')

当子类和父类存在相同名字的方法时(如上例run方法),子类会覆盖父类,不同子类拥有不同方法,这就是多态。

类其实也是一种数据类型:

Python基础笔记4如何高效学习?

a=list()#a是list类型
b=Animal()#b是Animal类型
c=Dog()#c是Dog类型

#判断变量是否为某种类型:
isinstance(a,list)
isinstance(b,Animal)
isinstance(c,Dog)

isinstance(c,Animal)#True
isinstance(b,Dog)#False

编写一个接受Animal类型变量的函数来理解多态:

defrun_twice(animal):
animal.run()
animal.run()

#以下都是Animal类型
run_twice(Animal())#Animalisrunning/Animalisrunning
run_twice(Cat())#Catisrunning/Catisrunning
run_twice(Dog())#Dogisrunning/Dogisrunning

传入的类型只要是Animal类或子类,就会自动调用实际类型的run()方法,这就是多态的意思。

多态真正的威力:调用方只管调用,不管细节,而当我们新增一种Animal的子类时,只要确保run()方法编写正确,不用管原来的代码是如何调用的。这就是著名的“开闭”原则:对扩展开放:允许新增Animal子类;对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。

继承可以一级一级地继承下来,而任何类最终都可以追溯到根类object。

Python作为动态语言,它的“file-like object“是一种“鸭子类型”,并不要求严格的继承体系。如上不一定需要传入Animal类型,只需要保证传入的对象有一个run()方法就可以了。

classTimer(object):
defrun(self):
print('start...')

4.获取对象信息

type()函数返回对应的Class类型

#基本类型
type(123)
type('str')
type(None)

#指向函数或类的变量
type(abs)
type(a)

type(123)=int#True
type('abc')=type(123)#False

判断一个对象是否为函数:

importtypes
deffn():
pass

type(fn)==types.FunctionType#True
type(abs)==types.BuiltinFunctionType
type(lambdax:x)==types.LambdaType
type((xforxinrange(10)))==types.GeneratorType

isinstance函数

#创建3种类型对象:
a=Animal()
d=Dog()
h=Husky()

#判断:
isinstance(h,Dog)
isinstance(h,Animal)

#type判断的类型也可用isinstance:
isinstance('abc',str)
#判断一个变量是否是某些类型中的一种
isinstance([1,2,3],(list,tuple))
isinstance((1,2,3),(list,tuple))

dir()函数
获得一个对象的所有属性和方法,返回list。

dir("abc")

len()函数内部自动调用该对象的​​__len__()​​方法:

len('abc')
'abc'.__len__()#效果同上

其他都是普通属性或方法,如lower:

'ABC'.lower()#abc

直接操作一个对象的状态:

#定义一个对象
classMyObject(object):
def__init__(self):
self.x=9
defpower(self):
returnself.x*self.x

obj=MyObject()

#测试对象的属性:
hasattr(obj,'x')#True是否有x属性
obj.x#9
hasattr(obj,'y')#False
setattr(obj,'y',19)#设置一个y属性
hasattr(obj,'y')#True
getattr(obj,'y')#19获取y属性
obj.y#19

getattr(obj,'z',404)#获取属性'z',如果不存在,返回默认值404

#获取对象的方法:
hasattr(obj,'power')
getattr(obj,'power')
fn=getattr(obj,'power')
fn#fn指向obj.power
fn()#同obj.power()

一个例子:

defreadImage(fp):
ifhasattr(fp,'read'):
returnreadData(fp)
returnNone

5.实例属性和类属性

根据类创建的实例可以任意绑定属性,方法是通过实例变量或self变量。

类属性直接在class中定义,这个属性虽然归类所有,但类的所有实例都可以访问到。实例属性属于各个实例所有,互不干扰。

classStudent(object):
name='Student'

s=Student()#创建实例s
print(s.name)#Student
print(Student.name)#Student

s.name='Jesse'#给实例绑定name属性
print(s.name)#Jesse实例属性优先级比类属性高
print(Student.name)#Student

dels.name
print(s.name)#Student

从上看出,最好不要对实例属性和类属性使用相同的名字。


作者:Bioinfarmer

若要及时了解动态信息,请关注同名微信公众号:Bioinfarmer。