模块

模块是一组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/env python3   #让文件直接在Unix上运行
# _*_ coding: utf-8 _*_ #使用utf-8编码 'a test module' #模块的文档注释 __author__='Jesse Peng' #作者变量 import sys #导入sys模块后,变量sys可以访问该模块所有功能 def test():
args = sys.argv #argv变量用list存储了命令行的所有参数
if len(args)==1: #第一个参数是.py文件的名称
print('hello, world!')
elif len(args)==2:
print('hello, %s!' % args[1])
else:
print('too many arguments!') if __name__=='__main__': #这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。
test()

命令行运行:

python3 hello.py
python3 hello.py Jesse

交互环境运行:

import hello
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 def greeting(name): #公有函数
if len(name)>3:
return _private1(name)
else:
return _private2(name)

上例中调用公有函数greeting()不用关心内部的私有函数细节,这是一种非常有用的代码封装和抽象的方法。

外部不需要引用的函数全部定义成private,只有外部需要引用的函数才定义为public。

2.安装第三方模块

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

pip install Pillow

安装常用模块。

使用anaconda,已经内置了许多第三方库。

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

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

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

二是设置环境变量PYTHONPATH.

面向对象编程OOP

面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。

面向对象的程序设计把计算机程序视为一组对象的集合,对象直接接收并处理消息,计算机执行对象间传递的消息。

所有数据类型都可为对象,也可自定义对象数据类型,也就是类(Class)的概念。

举例比较两者

面向过程:

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

面向对象:

class Student(object):
def __init__(self, name, score):
self.name = name #对象Student的name属性
self.score = score #对象Student的score属性 def print_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类,这是所有类最终都会继承的类。

class Student(object):
pass

创建实例:

通过类名()实现

bart = Student()
bart #instance
Student #class #自由给实例变量绑定属性
bart.name = 'bart'
bart.name

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

class Student(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类本身是关联起来的,我们称之为类的方法。

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.print_score()

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

class Student(object):
... def get_grade(self): #新增
if self.score >= 90:
return 'A'
elif self.score >= 60:
return 'B'
else:
return 'C' #调用
lisa = Student('Lisa', 99)
print(lisa.name, lisa.get_grade())

2.访问限制

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

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', 59)
bart.__name #error

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

class Student(object):
.......
def get_name(self):
return self.__name
def get_score(self):
return self.__score

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

    def set_score(self, score):
self.__score = score

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

class Student(object):
......
def set_score(self, score):
if 0 <= score <= 100:
self.__score = score
else:
raise ValueError('bad score')

__xxx__在Python中是特殊变量,不同于私有变量,可直接访问。而_name(一个下划线)变量外部也可访问,但尽量将它视为私有变量,不要随意访问。

实例中私有变量外部也是可以强制使用的,但不要这么做:

bart._Student__name  #bart

比较一下:

bart.__name = 'new name'
bart.__name #new name
#外部新设置了一个变量__name,而内部的__name并未改变 bart.get_name() #bart

3.继承和多肽

父类、子类

#父类
class Animal(object):
def run(self):
print('animal is running') #子类
class Dog(Animal):
pass
class Cat(Animal):
pass

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

dog=Dog()
dog.run() #来自父类的run方法:animal is running cat=Cat()
cat.run()

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

class Dog(Animal):
def run(self): #新增方法1
print('dog is running')
def eat(self): #新增方法2
print('eating meat')

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

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

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类型变量的函数来理解多态:

def run_twice(animal):
animal.run()
animal.run() #以下都是Animal类型
run_twice(Animal()) #Animal is running/Animal is running
run_twice(Cat()) #Cat is running/Cat is running
run_twice(Dog()) #Dog is running/Dog is running

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

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

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

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

class Timer(object):
def run(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

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

import types
def fn():
pass type(fn)==types.FunctionType #True
type(abs)==types.BuiltinFunctionType
type(lambda x: x)==types.LambdaType
type((x for x in range(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

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

#定义一个对象
class MyObject(object):
def __init__(self):
self.x=9
def power(self):
return self.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()

一个例子:

def readImage(fp):
if hasattr(fp, 'read'):
return readData(fp)
return None

5.实例属性和类属性

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

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

class Student(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 del s.name
print(s.name) #Student

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

Python基础笔记4的更多相关文章

  1. Python基础笔记系列十一:标准输入输出、文件读写和指针等操作

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 标准输入输出一.输入 在sublime中这个时候需要安装SublimeRE ...

  2. Python基础笔记系列一:基本工具与表达式

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 工具基础(Windows系统下)传送门:Python基础笔记系列四:工具的 ...

  3. 我的Python基础笔记

    Python是从刚开始参加工作,就有听各方面的测试大牛推崇,但是刚开始做测试时还是把基础的测试方法放在第一位来学习的,直到半年多以后才开始接触Python. 我的Python基础主要是以廖雪峰老师的在 ...

  4. Python基础笔记1

    这篇笔记来自廖雪峰的Python教程. 一.Python基础 Python使用缩进来组织代码块,务必遵守约定俗成的习惯,坚持使用4个空格的缩进. 在文本编辑器中,需要设置把Tab自动转换为4个空格,确 ...

  5. python基础笔记-0

    python中数据结构,主要有列表.元组.字典.集合. python中最基本数据结构是序列(sequence).序列中每个元素被分配一个序号——即元素位置,也成为索引.第一个索引是0,第二个是1,以此 ...

  6. Python基础笔记系列十四:python无缝调用c程序

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! python语言可以对c程序代码进行调用,以弥补python语言低性能的缺 ...

  7. Python基础笔记系列十三:socket网络编程

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!!使用python编写一个简易的服务端程序和客户端程序,启动服务端和客户端(监 ...

  8. Python基础笔记系列十二:requests模块的简单应用

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! httpbin httpbin这个网站能测试 HTTP 请求和响应的各种信 ...

  9. Python基础笔记系列十:模块

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 模块 #1.类比于java中的jar包,模块能让你能够有逻辑地组织你的Py ...

  10. Python基础笔记系列九:变量、自定义函数以及局部变量和全局变量

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 变量在前面的系列中也许就可以发现,python中的变量和C中的变量有些许不 ...

随机推荐

  1. 【UE4 设计模式】建造者模式 Builder Pattern

    概述 描述 建造者模式,又称生成器模式.是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 建造者模式将客户端与包含多个组成部分的复杂对象的创建过程分离,客户端无需知道复杂 ...

  2. MySQL:基础语法-3

    MySQL:基础语法-3 记录一下 MySQL 基础的一些语法,便于查询,该部分内容主要是参考:bilibili 上 黑马程序员 的课程而做的笔记,由于时间有点久了,课程地址忘记了 上文MySQL:基 ...

  3. UltraSoft - Beta - Scrum Meeting 10

    Date: May 26th, 2020. Scrum 情况汇报 进度情况 组员 负责 今日进度 q2l PM.后端 记录Scrum Meeting Liuzh 前端 暂无 Kkkk 前端 前端增加了 ...

  4. [Beta]the Agiles Scrum Meeting 4

    会议时间:2020.5.15 21:00 1.每个人的工作 今天已完成的工作 成员 已完成的工作 yjy 增加教学计划面板,修复bug tq 实现查看.删除测试点功能 wjx 实现批量创建结对项目功能 ...

  5. 字符串与模式匹配算法(一):BF算法

    一.BF算法的基本思想 BF(Brute Force)算法是模式匹配中最简单.最直观的算法.该算法最基本的思想是从主串的第 start 个字符起和模式P(要检索的子串)的第1个字符比较,如果相等,则逐 ...

  6. AOP源码解析:AspectJAwareAdvisorAutoProxyCreator类的介绍

    AspectJAwareAdvisorAutoProxyCreator 的类图 上图中一些 类/接口 的介绍: AspectJAwareAdvisorAutoProxyCreator : 公开了Asp ...

  7. vector之erase和迭代器

    C++开发中使用vector时非常方便的,但是也是需要非常小心的,最近在使用容器删除某个元素的时候,测试结果出现了异常 /* vector erase test*/ int testVector() ...

  8. kail入侵win2003 sp2 中文版系统

    攻击机:kail -- IP:192.168.74.132 目标靶机:win2003 sp2 中文版系统-- IP:192.168.74.128 一.扫描漏洞 1. 在kail中运行 namp 192 ...

  9. Effective java 读书笔记(2)

    第四条:通过私有构造器强化不可实例化的能力 有时可能需要编写只包含静态方法和静态域的类,这样的工具类不希望被实例化,因为实例化对它来说没有意义. 然而,在缺少显式构造器的情况下,系统会自动提供一个缺省 ...

  10. 使用python操作HDF5文件

    HDF Hierarchical Data Format,又称HDF5 在深度学习中,通常会使用巨量的数据或图片来训练网络.对于如此大的数据集,如果对于每张图片都单独从硬盘读取.预处理.之后再送入网络 ...