模块:

引用模块

作用域:

在一个模块中,我们可能会定义很多函数和变量,但有的函数和变量我们希望给别人使用,有的函数和变量我们希望仅仅在模块内部使用。在Python中,是通过_前缀来实现的。

正常的函数和变量名是公开的(public),可以被直接引用,比如:abc,x123,PI等;

类似__xxx__这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的__author__,__name__就是特殊变量,hello模块定义的文档注释也可以用特殊变量__doc__访问,我们自己的变量一般不要用这种变量名;

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

之所以我们说,private函数和变量“不应该”被直接引用,而不是“不能”被直接引用,是因为Python并没有一种方法可以完全限制访问private函数或变量,但是,从编程习惯上不应该引用private函数或变量。

private函数或变量不应该被别人引用,那它们有什么用呢?请看例子:

def _private_1(name):

return 'Hello, %s' % name

def _private_2(name):

return 'Hi, %s' % name

def greeting(name):

if len(name) > 3:

return _private_1(name)

else:

return _private_2(name)

我们在模块里公开greeting()函数,而把内部逻辑用private函数隐藏起来了,这样,调用greeting()函数不用关心内部的private函数细节,这也是一种非常有用的代码封装和抽象的方法,即:

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

模块搜索路径

当我们试图加载一个模块时,Python会在指定的路径下搜索对应的.py文件,如果找不到,就会报错:

>>> import mymodule

Traceback (most recent call last):

File "", line 1, in

ImportError: No module named mymodule

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

>>> import sys

>>> sys.path

['', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6', ..., '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages']

如果我们要添加自己的搜索目录,有两种方法:

一是直接修改sys.path,添加要搜索的目录:

>>> import sys

>>> sys.path.append('/Users/michael/my_py_scripts')

这种方法是在运行时修改,运行结束后失效。

第二种方法是设置环境变量PYTHONPATH,该环境变量的内容会被自动添加到模块搜索路径中。设置方式与设置Path环境变量类似。注意只需要添加你自己的搜索路径,Python自己本身的搜索路径不受影响。

面向对象的OOP

数据封装、继承和多态是面向对象的三大特点。向对象的设计思想是从自然界中来的,因为在自然界中,类(Class)和实例(Instance)的概念是很自然的。Class是一种抽象概念,比如我们定义的Class——Student,是指学生这个概念,而实例(Instance)则是一个个具体的Student,比如,Bart Simpson和Lisa Simpson是两个具体的Student。所以,面向对象的设计思想是抽象出Class,根据Class创建Instance。面向对象的抽象程度又比函数要高,因为一个Class既包含数据,又包含操作数据的方法。

面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板。类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响;方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节

访问限制:

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(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))

def get_name(self):

return self.__name

def get_score(self):

return self.__scor

继承与多态

继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写。

动态语言的鸭子类型特点决定了继承不像静态语言那样是必须的。

获取对象信息:

type判断对象类型

types中定义的常量函数

instance()函数

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

配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态

>>> class MyObject(object):

... def __init__(self):

... self.x = 9

... def power(self):

... return self.x * self.x

...

>>> obj = MyObject()

紧接着,可以测试该对象的属性:

>>> hasattr(obj, 'x') # 有属性'x'吗?

True

>>> obj.x

9

>>> hasattr(obj, 'y') # 有属性'y'吗?

False

>>> setattr(obj, 'y', 19) # 设置一个属性'y'

>>> hasattr(obj, 'y') # 有属性'y'吗?

True

>>> getattr(obj, 'y') # 获取属性'y'

19

>>> obj.y # 获取属性'y'

19

实例属性和类属性

实例属性属于各个实例所有,互不干扰;

类属性属于类所有,所有实例共享一个属性;不要对实例属性和类属性使用相同的名字,否则将产生难以发现的错误

python允许动态绑定属性和方法

class Student(object):

pass

然后,尝试给实例绑定一个属性:

>>> s = Student()

>>> s.name = 'Michael' # 动态给实例绑定一个属性

>>> print(s.name)

Michael

还可以尝试给实例绑定一个方法:

>>> def set_age(self, age): # 定义一个函数作为实例方法

... self.age = age

...

>>> from types import MethodType

>>> s.set_age = MethodType(set_age, s) # 给实例绑定一个方法

>>> s.set_age(25) # 调用实例方法

>>> s.age # 测试结果

25

使用__slots__

限制实例的属性

比如,只允许对Student实例添加name和age属性。

为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:

class Student(object):

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

然后,我们试试:

>>> s = Student() # 创建新的实例

>>> s.name = 'Michael' # 绑定属性'name'

>>> s.age = 25 # 绑定属性'age'

>>> s.score = 99 # 绑定属性'score'

Traceback (most recent call last):

File "", line 1, in

AttributeError: 'Student' object has no attribute 'score'

由于'score'没有被放到__slots__中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。

使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的:

>>> class GraduateStudent(Student):

... pass

...

>>> g = GraduateStudent()

>>> g.score = 9999

除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__。

使用@property

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

class Student(object):

@property

def score(self):

return self._score

@score.setter

def score(self, value):

if not isinstance(value, int):

raise ValueError('score must be an integer!')

if value < 0 or value > 100:

raise ValueError('score must between 0 ~ 100!')

self._score = value

@property的实现比较复杂,我们先考察如何使用。把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作

多重继承

class Dog(Mammal, RunnableMixIn, CarnivorousMixIn):

pass

定制类

__str__和__repr__

class Student(object):

def __init__(self, name):

self.name = name

def __str__(self):

return 'Student object (name=%s)' % self.name

__repr__ = __str__

__iter__、__getattr__、__call__

使用枚举类:

from enum import Enum

Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

value属性则是自动赋给成员的int常量,默认从1开始计数。

如果需要更精确地控制枚举类型,可以从Enum派生出自定义类:

from enum import Enum, unique

@unique

class Weekday(Enum):

Sun = 0 # Sun的value被设定为0

Mon = 1

Tue = 2

Wed = 3

Thu = 4

Fri = 5

Sat = 6

@unique装饰器可以帮助我们检查保证没有重复值。

访问这些枚举类型可以有若干种方法:

>>> day1 = Weekday.Mon

>>> print(day1)

Weekday.Mon

>>> print(Weekday.Tue)

Weekday.Tue

>>> print(Weekday['Tue'])

Weekday.Tue

>>> print(Weekday.Tue.value)

2

>>> print(day1 == Weekday.Mon)

True

>>> print(day1 == Weekday.Tue)

False

>>> print(Weekday(1))

Weekday.Mon

>>> print(day1 == Weekday(1))

True

>>> Weekday(7)

Traceback (most recent call last):

...

ValueError: 7 is not a valid Weekday

>>> for name, member in Weekday.__members__.items():

... print(name, '=>', member)

...

Sun => Weekday.Sun

Mon => Weekday.Mon

Tue => Weekday.Tue

Wed => Weekday.Wed

Thu => Weekday.Thu

Fri => Weekday.Fri

Sat => Weekday.Sat

可见,既可以用成员名称引用枚举常量,又可以直接根据value的值获得枚举常量。

元类:

type()函数既可以返回一个对象的类型,又可以创建出新的类型,比如,我们可以通过type()函数创建出Hello类,而无需通过class Hello(object)...的定义。

>>> def fn(self, name='world'): # 先定义函数

... print('Hello, %s.' % name)

...

>>> Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class

>>> h = Hello()

>>> h.hello()

Hello, world.

>>> print(type(Hello))

>>> print(type(h))

要创建一个class对象,type()函数依次传入3个参数:

class的名称;

继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;

class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。

metaclass

除了使用type()动态创建类以外,要控制类的创建行为,还可以使用metaclass。

metaclass,直译为元类,简单的解释就是:

当我们定义了类以后,就可以根据这个类创建出实例,所以:先定义类,然后创建实例。

但是如果我们想创建出类呢?那就必须根据metaclass创建出类,所以:先定义metaclass,然后创建类。

连接起来就是:先定义metaclass,就可以创建类,最后创建实例。

所以,metaclass允许你创建类或者修改类。换句话说,你可以把类看成是metaclass创建出来的“实例”。

错误、调试和测试

try...except...finally

try:

print('try...')

r = 10 / int('2')

print('result:', r)

except ValueError as e:

print('ValueError:', e)

except ZeroDivisionError as e:

print('ZeroDivisionError:', e)

else:

print('no error!')

finally:

print('finally...')

print('END')

出错的时候,一定要分析错误的调用栈信息,才能定位错误的位置。

raise

# err_reraise.py

def foo(s):

n = int(s)

if n==0:

raise ValueError('invalid value: %s' % s)

return 10 / n

def bar():

try:

foo('0')

except ValueError as e:

print('ValueError!')

raise

bar()

Python内置的try...except...finally用来处理错误十分方便。出错时,会分析错误信息并定位错误发生的代码位置才是最关键的。

程序也可以主动抛出错误,让调用者来处理相应的错误。但是,应该在文档中写清楚可能会抛出哪些错误,以及错误产生的原因。

assert() 断言

def foo(s):

n = int(s)

assert n != 0, 'n is zero!'

return 10 / n

def main():

foo('0')

logging

import logging

logging.basicConfig(level=logging.INFO)

s = '0'

n = int(s)

logging.info('n = %d' % n)

print(10 / n)

断点,调试

注意:断言的开关“-O”是英文大写字母O,不是数字0。

单元测试:

class Dict(dict):

def __init__(self, **kw):

super().__init__(**kw)

def __getattr__(self, key):

try:

return self[key]

except KeyError:

raise AttributeError(r"'Dict' object has no attribute '%s'" % key)

def __setattr__(self, key, value):

self[key] = value

为了编写单元测试,我们需要引入Python自带的unittest模块,编写mydict_test.py如下:

import unittest

from mydict import Dict

class TestDict(unittest.TestCase):

def test_init(self):

d = Dict(a=1, b='test')

self.assertEqual(d.a, 1)

self.assertEqual(d.b, 'test')

self.assertTrue(isinstance(d, dict))

def test_key(self):

d = Dict()

d['key'] = 'value'

self.assertEqual(d.key, 'value')

def test_attr(self):

d = Dict()

d.key = 'value'

self.assertTrue('key' in d)

self.assertEqual(d['key'], 'value')

def test_keyerror(self):

d = Dict()

with self.assertRaises(KeyError):

value = d['empty']

def test_attrerror(self):

d = Dict()

with self.assertRaises(AttributeError):

value = d.empty

setUp与tearDown

可以在单元测试中编写两个特殊的setUp()和tearDown()方法。这两个方法会分别在每调用一个测试方法的前后分别被执行。

setUp()和tearDown()方法有什么用呢?设想你的测试需要启动一个数据库,这时,就可以在setUp()方法中连接数据库,在tearDown()方法中关闭数据库,这样,不必在每个测试方法中重复相同的代码:

class TestDict(unittest.TestCase):

def setUp(self):

print('setUp...')

def tearDown(self):

print('tearDown...')

文档测试

python 3.0_python基础3.0相关推荐

  1. 买《Python数据分析师:从0基础到数据分析达人》专题视频课程送纸质图书

    <Python从小白到大牛>纸质图书于2018年10月上市,为了答谢广大学员对智捷课堂以及关老师的支持,现购买51CTO学院([Python数据分析师:从0基础到数据分析达人](https ...

  2. python 基础 9.0 安装MySQL-python-1.2.5客户端

    一. 安装客户端     python 标准数据库接口为Python DB-API,Python DB-API 为开发人员提供了数据应用编程接口.参考地址:https://wiki.python.or ...

  3. 计算机编程书籍-笨办法学Python 3:基础篇+进阶篇

    编辑推荐: 适读人群 :本书适合所有已经开始使用Python的技术人员,包括初级开发人员和已经升级到Python 3.6版本以上的经验丰富的Python程序员. "笨办法学"系列, ...

  4. Python的零基础超详细讲解(第七天)-Python的数据的应用

    往期文章 Python的零基础超详细讲解(第一天)-Python简介以及下载_编程简单学的博客-CSDN博客 Python的零基础超详细讲解(第二天)-Python的基础语法1_编程简单学的博客-CS ...

  5. Python的零基础超详细讲解(第五天)-Python的运算符

    往期文章 Python的零基础超详细讲解(第一天)-Python简介以及下载_编程简单学的博客-CSDN博客 Python的零基础超详细讲解(第二天)-Python的基础语法1_编程简单学的博客-CS ...

  6. Python语言编程基础

    Python 技能目标 理解编程基本原理和思想 掌握python语言的基础语法 能够使用python进行基本的开发工作 熟练使用项目开发IDE:eclipse,PyDev 能够使用Python开发简单 ...

  7. python编程语法大全-Python编程入门——基础语法详解

    今天小编给大家带来Python编程入门--基础语法详解. 关于怎么快速学python,可以加下小编的python学习群:611+530+101,不管你是小白还是大牛,小编我都欢迎,不定期分享干货 每天 ...

  8. python编程语法-Python编程入门——基础语法详解

    今天小编给大家带来Python编程入门--基础语法详解. 一.基本概念 1.内置的变量类型: Python是有变量类型的,而且会强制检查变量类型.内置的变量类型有如下几种: #浮点 float_num ...

  9. python编程if语法-Python编程入门基础语法详解经典

    原标题:Python编程入门基础语法详解经典 一.基本概念 1.内置的变量类型: Python是有变量类型的,而且会强制检查变量类型.内置的变量类型有如下几种: #浮点 float_number = ...

  10. python编程语法-Python编程入门——基础语法详解(经典)

    今天小编给大家带来Python编程入门--基础语法详解.温馨提示: 亮点在最后! 在这里还是要推荐下我自己建的Python开发学习群:301056051,群里都是学Python开发的,如果你正在学习P ...

最新文章

  1. 如何利用装饰者模式在不改变原有对象的基础上扩展功能
  2. pb数据窗口显示图片_PowerPhotos帮助你再Mac系统上更好,更快的管理自己的图片...
  3. pyspark pipline
  4. __str__的用法
  5. 城市问题(Floyd)
  6. 牛客 - 拿物品(贪心)
  7. ABAP 标准培训教程 BC400 学习笔记之四:ABAP 编程语言的数据类型
  8. 语音编码分类及编解码标准
  9. Vue中富文本编辑器的使用
  10. 修改服务器的共享内存大小,服务器共享内存大小能改么
  11. linux iso作为安装源,linux下使用iso文件做为yum安装源
  12. C# MD5加密与解密
  13. 你家的APS系统有这些功能吗?排程系统功能盘点
  14. C语言输出AB9798,c语言基础练习习题及答案.doc
  15. moodle安装图解
  16. 为什么远程计算机后会黑屏,解决Win10电脑远程桌面黑屏的问题
  17. 移远M26实现短信接收
  18. 重学JavaWeb —— Servlet,简单全面一发入魂
  19. java使用阿里云发送通知短信
  20. python爬虫模拟登录网页:登录wish

热门文章

  1. pg库使用dblink连接mysql_PG-跨库操作-dblink
  2. python iloc iat_python数据预处理_DataFrame数据筛选loc,iloc,ix,at,iat
  3. Java基础Arrays类
  4. Android真机调试时LogCat不显示日志信息
  5. mysql sql语句 参数化_MySQL存储过程准备语句(动态SQL)参数化
  6. php 中echo用法,php中echo()函数的用法(附代码)
  7. php保存上传的音频文件在哪里,php 视频、音频和图片文件上传,该如何解决
  8. 请检查 mysql 模块是否正确加载_mysql_connect() 不支持 请检查 mysql 模块是否正确加载...
  9. 单片机r6/r7c语言怎么用,第5章MCU混合编程与C语言和汇编语言
  10. c语言中函数的递归调用,用C语言函数调用与递归解决问题