模块相关基础
1.1模块的格式:
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
'这是一个注释'
__author__='lnssm'
import sys
def test():
args=sys.argv
if len(args)==1:
print('hello world')
elif len(args)==2:
print('hello %s'%args[1])
else:
print('to many argument!')
if __name__='__main__':
test()
解释:
-
第一行和第二行是标准注释,第一行注释可以让这个文件直接在unix/linux/mac
上运行,第二行是说明使用utf-8编码
-
第三行是一个字符串,表示模块的注释,任何模块代码的第一个字符串出现都被当作是模块的文档注释
-
第4行使用__author__
变量,把作者写进去,注意这是两个划线
-
第5行是引入模块,导入sys
模块后,我们就有了变量sys
指向该模块,利用sys
这个变量,就可以访问sys
模块的所有功能。sys
模块有一个argv
变量,用list存储了命令行的所有参数。argv
至少有一个元素,因为第一个参数永远是该.py文件的名称,例如:
运行python3 hello.py
获得的sys.argv
就是['hello.py']
;
运行python3 hello.py Michael
获得的sys.argv
就是['hello.py', 'Michael]
。
-
第6行是真正的写的功能
注意下
if __name__='__main__':
test()
虽然php没有相应的入口函数,但是像c
,java
,go
等都有入口函数main,你就可以把它作为是,就行了,引申一下就是,就我们在命令行执行这个模块文件时,python解释器把一个特殊变量__name__
置为__main__
1.2 作用域
在一个模块中,我们可以定义多个变量与函数,但有些函数或变量,只是为这个模块自己使用的,不想让别的模块调用,这个时候作用域就出现了
格式:使用_变量
或者__函数
来表示,相当于一个private函数或者变量了,但是在python中,没有绝对的private变量,也就是说你用了也不会有什么错,只是我们不用罢了
def _private_1(name):
return 'hello %s'%name
def _private_2(name):
return 'hello %s'%name
2.1 安装第三方库
a.在python中使用pip
包管理工具进行操作
第三方库资源官网:pypi.python.org
pip
使用:
>>> pip help #查看帮助信息
>>> pip install 包名 安装包
>>> pip uninstall 包名 卸载包
还可以安装 anaconda官网提供的gui安装包,常用的包都在里面
b. 模块搜索路径
默认情况下,python解释器会搜索当前目录,所有已安装的内置模块和第三方模块,搜索路径都会放在sys
模块中path变量中
>>> import sys
>>> sys.path
如果我们要添加自己的搜索目录,有两种方法
-
直接修改sys.path
>>> import sys
>>> sys.path.append('/usrs/my_py_scripts')
-
设置环境变量PYTHONPATH
,该环境变量的内容会被自动添加到模块搜索路径中。设置方式与设置Path环境变量类似。注意只需要添加你自己的搜索路径,Python自己本身的搜索路径不受影响。
2. 面向对象编程(oop)
2.1 类和实例:
- 定义:它和
php
也差不多,定义类通过class
关键字,它们也有封装
,继承
,多态
三大特型
#定义一个类
class Student(object):
class
后面紧接着是类名,类名通常是大写开头的单词,紧接着是(object) 表示该类是从哪个类继承过来的
>>> student=Student()
-
如果在创建类的时候初始化参数,python提供了一个__init__(self,name,age)
和php
中的__construct()
功能差不多,都是初始化一些数据的
class Student(object):
def __init__(self,name,age):
self:name=name
self:age=age
__init__()
的第一个参数永远是self
,表示创建的实例本身,当然这个值不用传
2.1 访问限制,
如何实现在class内部,属性和方法,不能通过外部调用直接赋值呢?
可以在方法或者属性前面添加__
class Student(object):
def __init__(self,name,age):
self.__name=name
self.__age=age
这样在外面就不可以访问了,如果想修改里面的值可以这样来操作
class Student(object):
def __init__(self,name,age):
self.__name=name
self.__age=age
def get_name(self):
return self.__name
def set_name(self,name):
self.__name=name
小demo:
class Student:
def __init__(self,name,gender):
self.name=name
self.__gender=gender
def get_gender(self):
return self.__gender
def set_gender(self,name):
self.__gender=name
# 测试:
bart = Student('Bart', 'male')
if bart.get_gender() != 'male':
print('测试失败!')
else:
bart.set_gender('female')
if bart.get_gender() != 'female':
print('测试失败!')
else:
print('测试成功!')
3.获取对象
3.1
- 方法: 可以使用
type()
函数来判断基本
类型,如果要判断一个对象是否是函数,则需要使用types
模块中定义的常量,来判断了
>>> import types
>>> def fn():
pass
>>>type(fn)=types.FunctionType
>>> True
- 还可以使用`isinstance()来判断class 的类型
如果是继承的关系
object->animal->dog->hushky
>>> a=Animal()
>>>b=Dog()
>>> c=Hushky()
>>> isinstance(h,hushky)
>>> True
>>> isinstance(c,Dog)
>>> True #这是因为hushk是从dog上面继承下来的,也属性dog的一部分
-
还可以判断一个变量是不是某些类型中的一种,
>>> isinstance([1,2,3],(list,tuple)) 判断是否是list或tu
3.2 获取对象里的所在属性和方法
dir()
函数:可以使用dir()
函数,它返回一个包含字符串的list
getattr()
函数:获得一个对象的属性
setattr()
函数;设置一个对象的属性
hasattr()
函数:判断一个对象的属性是否存在,如果是私有属性可返回false
3.3 __slots__
属性
说明:创建实例时,能限制该实例能添加的属性,只在当前类有效,在继承类里使用无效,如果子类里想使用,则需要在子类里定义__slots__
,才可以.
小demo:
#定义一个Student类
class Student:
__slots__=('name','age')
>>> s=Student()
>>> s.name=lnssm
>>> s.age=18
>>> s.sex=u # 这是报错了
3.4 @property
属性
验证参数是否符合预期,当我们想为一个属性赋值时,需要进行判断合法性,需要使用@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 is integer)
if value<0 or value>100
raise ValueError('score must 0~100)
self._score=value
@property
的实现比较复杂,我们先考察如何使用。把一个getter方法变成属性,只需要加上@property
就可以了,此时,@property
本身又创建了另一个装饰器@score.setter
,负责把一个setter方法变成属性赋值,注意到这个神奇的@property
,我们在对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过getter和setter方法来实现的。
还可以定义一个只读属性,方法是只定义一个getter
方法,而不定义一个setter
方法
class Student(object):
@property
def birth(self):
return self._brith
@birth.setter
def birth(self,value):
self._brith=value
@property
def age(self):
return 2019-self._brith
请利用@property
给一个Screen
对象加上width
和height
属性,以及一个只读属性resolution
:
class Screen(object):
@property
def width(self):
return self._width
@width.setter
def width(self,value):
self._width=value
@property
def height(self):
return self._height
@height.setter
def height(self,value):
self._height=value
@property
def resolution(self):
return self._height* self._width
# 测试:
s = Screen()
s.width = 1024
s.height = 768
print('resolution =', s.resolution)
if s.resolution == 786432:
print('测试通过!')
else:
print('测试失败!')
4. python是支持多继承的,php 是单继承的
在设计类的继承关系时,通常,主线都是单一继承下来的,例如,Ostrich
继承自Bird
。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,比如,让Ostrich
除了继承自Bird
外,再同时继承Runnable
。这种设计通常称之为MixIn
。
5.定制类
5.1 __str__
:可以使用打印信息美化,类似于es或mongo里的pretty
功能
class Student(object):
def __init__(self,name):
self.name=name
def __str__(self):
return 'Stuent object (name:%s)' % self.name
5.2 __iter__
该方法返回一个迭代对象,Python的for循环就会不断调用该迭代对象的__next__()
方法拿到循环的下一个值,直到遇到StopIteration
错误时退出循环。
class Fib(object):
def __init__(self):
self.a,self.b=0,1
def __iter__(self):
return self
def __next__(self):
self.a,self.b=self.b,self.a+self.b
if self.a>10000:
rasie StopIteration()
return self.a
5.3 __getitem__
实现这个方法可以实现通过下标取出元素
class Student(object):
def __getitem(self,n):
a,b=1,1
for x in range(n):
a,b=b,a+b
return a
5.4 __getattr__
调用不存在的方法或属性时,会触发
class Student(object):
def __init__(self):
self.name='lnssm'
def __getattr__(self,attr):
if attr=='score':
return 999;
5.5 __call__
以访问方法的方式去调用对象
class Student(object):
def __init__(self,name):
self.name=name
def __call__(self):
pritf('this is %s' % self.name)
#调用方法如下
>>> s=Student('lnssm')
>>>s()
可以使用callable()
函数可以判断一个对象是否是可调用对象
6.异常处理
6.1 捕获异常
python中可以使用try...expect...finally
来处理,python错误其实也是一个class ,所有的错误类型都继承自BaseException
try:
print('try...')
r = 10 / 0
print('result:', r)
except ZeroDivisionError as e:
print('except:', e)
finally:
print('finally...')
print('END')
6.2 记录错误
python内置的logging
模块可以非常容易的地记录错误信息
import logging
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
try:
bar('0')
except Exception as e:
logging.exception(e)
main()
print('END')
6.3 抛出异常
使用raise
语句
# err_raise.py
class FooError(ValueError):
pass
def foo(s):
n = int(s)
if n==0:
raise FooError('invalid value: %s' % s)
return 10 / n
foo('0')
7.调式
7.1 方式
-
print()
-
assert()
断言
def foo(s):
n=int(s)
assert n!=0,'n is zero' 相当于三元运算吧,断言`n !=0`为True,否则输出后面的语句
-
logging
模块,
improt logging
logging.basicConfig(level=logging.INFO) #这是设置记录信息的级别,有`debug`,`info`,`warning`,`error`
-
pdb
启动Python的调试器pdb,让程序以单步方式运行,可以随时查看运行状态。我们先准备好程序:
-
pdb.set_trace()
这个方法也是用pdb,但是不需要单步执行,我们只需要import pdb
,然后,在可能出错的地方放一个pdb.set_trace()
,就可以设置一个断点:
# err.py
import pdb
s = '0'
n = int(s)
pdb.set_trace() # 运行到这里会自动暂停
print(10 / n)