Python核心基础:之三:封装

来源:互联网 发布:力矩电机控制算法 编辑:程序博客网 时间:2024/06/04 01:32
参考:http://www.runoob.com/python/python-tutorial.html
  • 函数
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
函数内容以冒号起始,并且缩进。
return [表达式] 结束函数,选择性地返回一个值给调用方。
不带表达式的return相当于返回 None。

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。
python 函数的参数传递:
不可变类型:类似值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
可变类型:类似引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响
python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
参数
以下是调用函数时可使用的正式参数类型:
必备参数,关键字参数, 默认参数, 不定长参数

必备参数
必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。不然会出现语法错误

关键字参数
关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。
def printinfo( name, age ):
   "打印任何传入的字符串"
   print "Name: ", name;
   print "Age ", age;
   return;
#调用printinfo函数
printinfo( age=50, name="miki" ); #次序和定义的不同

缺省参数
调用函数时,缺省参数的值如果没有传入,则被认为是默认值。
def printinfo( name, age = 35 ):

不定长参数
加了星号(*)的变量名会存放所有未命名的变量参数。选择不多传参数也可。
def printinfo( arg1, *vartuple ):
   "打印任何传入的参数"
   print "输出: "
   print arg1
   for var in vartuple:
      print var
   return;
匿名函数
python 使用 lambda 来创建匿名函数。
lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
sum = lambda arg1, arg2: arg1 + arg2;
命名空间
每个函数都有自己的命名空间。类的方法的作用域规则和通常函数的一样。
Python 会智能地猜测一个变量是局部的还是全局的,它假设任何在函数内赋值的变量都是局部的。
因此,如果要给函数内的全局变量赋值,必须使用 global 语句。

def AddMoney():
   # 想改正代码就取消以下注释:
   # global Money
   Money = Money + 1 #内部赋值,默认是局部变量
在函数内给变量 Money 赋值,然后 Python 会假定 Money 是一个局部变量。然而,我们并没有在访问前声明一个局部变量 Money,结果就是会出现一个 UnboundLocalError 的错误。

  • 模块
Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句。
模块能定义函数,类和变量

下例是个简单的模块 support.py,文件中代码为:
def print_func( par ):
   print "Hello : ", par
   return
模块的引入
模块定义好后,我们可以使用 import 语句来引入模块。一个模块只会被导入一次,不管你执行了多少次import。这样可以防止导入模块被一遍又一遍地执行。
在调用 math 模块中的函数时,必须这样引用:模块名.函数名

最常规的导入
import module1[, module2[,... moduleN]

Python 的 from 语句让你从模块中导入一个指定的部分到当前命名空间中。
from modname import name1[, name2[, ... nameN]]
from modname import * #一个模块的所有内容全都导入到当前的命名空间
当你导入一个模块,Python 解析器对模块位置的搜索顺序是:
1、当前目录
2、如果不在当前目录,Python 则搜索在 shell 变量 PYTHONPATH 下的每个目录。
3、如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/。
模块搜索路径存储在 system 模块的 sys.path 变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。
常用函数
dir() 函数一个排好序的字符串列表,内容是一个模块里定义过的名字。返回的列表容纳了在一个模块里定义的所有模块,变量和函数。

globals() 和 locals() 函数可被用来返回全局和局部命名空间里的名字。两个函数的返回类型都是字典。
如果在函数内部调用 locals(),返回的是所有能在该函数里访问的命名。
如果在函数内部调用 globals(),返回的是所有在该函数里能访问的全局名字。

reload() 函数
当一个模块被导入到一个脚本,模块顶层部分的代码只会被执行一次。因此,如果你想重新执行模块里顶层部分的代码,可以用 reload() 函数。该函数会重新导入之前导入过的模块。

包是一个分层次的文件目录结构,简单来说,包就是文件夹,但该文件夹下必须存在 __init__.py 文件, 该文件的内容可以为空。__int__.py用于标识当前文件夹是一个包。

  • 面向对象

Python从设计之初就已经是一门面向对象的语言。使用class语句来创建一个新类,class之后为类的名称并以冒号结尾

类的帮助信息可以通过ClassName.__doc__查看。

class Employee:
   '所有员工的基类’ #第一行是可选的注释
   empCount = 0
   def __init__(self, name, salary):
      self.name = name
      self.salary = salary
      Employee.empCount += 1

第一种方法__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法

类的方法,在类的内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数

self 代表类的实例,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类。

实例化类其他编程语言中一般用关键字 new,但是在 Python 中并没有这个关键字,类的实例化类似函数调用方式。
emp1 = Employee("Zara", 2000)

你可以添加,删除,修改类的属性,也就是说,不需要收类定义的限制!如下所示:
emp1.age = 7  # 添加一个 'age' 属性
emp1.age = 8  # 修改 'age' 属性
del emp1.age  # 删除 'age' 属性
Python内置类属性
__dict__ : 类的属性(包含一个字典,由类的数据属性组成)
__doc__ :类的文档字符串
__name__: 类名
__module__: 类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
__bases__ : 类的所有父类构成元素(包含了一个由所有父类组成的元组)
python对象销毁(垃圾回收)
Python 使用了引用计数这一简单技术来跟踪和回收垃圾。
当对象被创建时, 就创建了一个引用计数, 当这个对象不再需要时, 也就是说, 这个对象的引用计数变为0 时, 它被垃圾回收。但是回收不是"立即"的, 由解释器在适当的时机,将垃圾对象占用的内存空间回收。
Python 的垃圾收集器实际上是一个引用计数器和一个循环垃圾收集器。

析构函数 __del__ ,__del__在对象销毁的时候被调用
类的继承
需要注意的地方:继承语法 class 派生类名(基类名)://... 基类名写在括号里
在python中继承中的一些特点:
1:在继承中基类的构造(__init__()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用。
2:在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别于在类中调用普通函数时并不需要带上self参数
3:先在本类中查找调用的方法,找不到才去基类中找。

如果在继承元组中列了一个以上的类,那么它就被称作"多重继承” 。
class A:        # 定义类 A
.....
class B:         # 定义类 B
.....
class C(A, B):   # 继承类 A 和 B
…..

与继承相关的方法。
issubclass() - 布尔函数判断一个类是另一个类的子类或者子孙类,语法:issubclass(sub,sup)
isinstance(obj, Class) 布尔函数如果obj是Class类的实例对象或者是一个Class子类的实例对象则返回true。
方法重写
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法:
class Parent:        # 定义父类
   def myMethod(self):
      print '调用父类方法'
class Child(Parent): # 定义子类
   def myMethod(self):
      print '调用子类方法’ #重写了,方法定义是一模一样的

列出了一些通用的功能,你可以在自己的类重写:
__init__ ( self [,args...] )
简单的调用方法: obj = className(args)
__del__( self )
简单的调用方法 : dell obj
__repr__( self )
简单的调用方法 : repr(obj)
__str__( self )
简单的调用方法 : str(obj)
__cmp__ ( self, x )
简单的调用方法 : cmp(obj, x)

运算符重载
class Vector:
   def __init__(self, a, b):
      self.a = a
      self.b = b
   def __str__(self):
      return 'Vector (%d, %d)' % (self.a, self.b)
   def __add__(self,other):
      return Vector(self.a + other.a, self.b + other.b)

v1 = Vector(2,10)
v2 = Vector(5,-2)
print v1 + v2
类的私有属性 __private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。

类的私有方法 __private_method:两个下划线开头,声明该方法为私有方法,不能在类地外部调用。在类的内部调用 self.__private_methods

Python不允许实例化的类访问私有数据或方法,但你可以使用 object._className__attrName 访问属性

_foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import *


注:
    按照模块划分的项目,运行中的基础机制,预定义值__name__。 假设有两个模块,A.py 和 B.py
A.py
import logging

logger = logging.getLogger(__name__)
logger.info("Current Module" + __name__) #日志打印模块
print "Current Module" + __name__ #模块打印

def some_function(xxxx): 
    xxxxxxx

if __name__ == '__main__’: #单独运行A,则__name__就等等于__main__,从而这个判断可以执行
    some_function(xxxxxx)
B.py
if __name__ == '__main__':
    import logging
    logging.basicConfig(level='DEBUG')
    import A #引入A模块,触发的日志打印和模块打印,出来的将是模块的名字,而不是__main__


原创粉丝点击