python学习笔记(4)

44、模块
(1)修改搜索路径
在交互模式下修改sys.path,将自己写的模块所在的目录放到这个搜索路径中,那么解释器就可以找到在这个路径下所定义的模块了,示例:
>>>import sys
>>> sys.path.append(r'E:\My DBank\python\py\mymodule')

若要移除这个路径,那么可以使用列表中的pop()方法

(2)名称空间
名称空间是名称(标识符)到对象的映射,向名称空间添加名称的操作过程涉及到绑定标识符到
指定对象的操作(以及给该对象的引用计数加 1 )。

在执行期间有两个或三个活动的名称空间。 这三个名称空间分别是局部名称空间, 全局名称空间和内建名称空间, 但局部名称空间在执行期间是不断变化的, 所以我们说"两个或三个"。


Python 解释器首先加载内建名称空间。 它由 __builtins__ 模块中的名字构成。 随后加载执
行模块的全局名称空间, 它会在模块开始执行后变为活动名称空间。如果在执行期间调用了一个函数, 那么将创建出第三个名称空间, 即局部名称空间。

通过 globals() 和 locals() 内建函数判断出某一名字属于哪个名称空间


在遇到名称空间的时候想想"它存在吗?", 遇到变量作用域的时候想想"我能看见它吗?"

(3)使用类实例来创建名称空间
有点晕啊,python怎么那么随便呢?竟然可以这样来写类,而且可以在外部动态的给类添加属性,有点接受不了啊,使用类实例可以充当命名空间,这个。。。不知道该怎么说啊

>>> class MyClass(object):
	pass

>>> bag=MyClass()
>>> bag.x=100
>>> bag.y=200
>>> bag.version=0.1
>>> bag.completed=False

>>> bag.y
200
>>> bag.version
0.1

(4)推荐的模块导入顺序
我们推荐所有的模块在 Python 模块的开头部分导入。 而且最好按照这样的顺序:
   Python 标准库模块
   Python 第三方模块
   应用程序自定义模块


(5)扩展的模块导入语句(as)
使用as关键字,可以将导入的模块的名字或者是导入的模块的属性的名字换成你想要的名字,如下:
>>>import MyModule as m
>>> m.test()
ran test()


>>> from MyModule import test as t
>>> t()
ran test()


(6)导入到当前名称空间的名称
一个模块只被加载一次,不管它被导入多少次。
调用 from-import 可以把名字导入当前的名称空间里去。

有时候使用from-import语句导入的模块中的属性,会和程序之前所定义的变量相冲突,遇到这种情况,唯一的解决办法,就是不要使用from-import语句,而是通过模块名字来调用属性,以防止冲突


(7)模块内建函数
1. __import__()

import语句是通过调用__import__()函数来完成导入的工作的,语法为:

__import__(module_name[, globals[, locals[, fromlist]]])


2. globals()和locals()
globals() 和 locals() 内建函数分别返回调用者全局和局部名称空间的字典
在一个函数内部, 局部名称空间代表在函数执行时候定义的所有名字, locals() 函数返回的就是包含这些名字的字典。 globals() 会返回函数可访问的全局名字。
在全局名称空间下, globals() 和 locals() 返回相同的字典, 因为这时的局部名称空间就是全局空间
在局部名称空间下,globals()返回的是全局的的名称空间的字典,而lobals()返回局部的名称空间的字典。


示例:
>>> def foo():    #局部
        print 'calling foo()...'
        aString='bar'
        anInt=42
        print 'foo() globals: ', globals().keys()
        print 'foo() lobals: ', locals().keys()


#全局	
>>> print '__main__ globals: ', globals().keys()
__main__ globals:  ['__builtins__', '__package__', '__name__', 'foo', '__doc__']


>>> print '__main__ locals: ',locals().keys()
__main__ locals:  ['__builtins__', '__package__', '__name__', 'foo', '__doc__']


>>> foo()
calling foo()...
foo() globals:  ['__builtins__', '__package__', '__name__', 'foo', '__doc__']
foo() lobals:  ['anInt', 'aString']


(8)包
包是一个有层次的文件目录结构, 它定义了一个由模块和子包组成的 Python 应用程序执行环境。

就好像java中的包的概念是类似的,而且与类和模块相同, 包也使用句点属性标识来访问他们的元素。

示例:
import Phone.Mobile.Analog
from Phone import Mobile
from Phone.Mobile.Analog import dial
from package.module import *

(9)相对导入和绝对导入
import 语句总是绝对导入的, 所以相对导入只应用于 from-import 语句。

(10)# -*- coding: UTF-8 -*-
使用指定的编码格式来解析模块文件


45、面向对象编程
(1)类最简单的使用情况就是使用类作为命名空间,这就像c++中的结构体一样,但是这样在类外加进去的属性属于类实例的属性,并不是类的属性,这些属性实质上是动态的,不需要在其他的地方预先声明

(2)类通常在一个模块的顶层进行定义,以便类实例能够在类所定义的源代码文件中的任何地方被创建

(3)类属性

属性就是属于一个对象的数据或者函数元素,包括数据属性和函数属性,即数据和函数都属于属性的范畴


1. 实例数据属性:

2. 类数据属性:仅当需要有更加“静态”数据类型时才变得有用,它和任何实例都无关,它相当于java中的静态变量,即用static标志的成员变量。如下:

>>> class C(object):
foo=100    #foo即为C类的数据属性

3. 方法
类中的方法必须通过类实例的点调用来访问,即方法必须绑定(到一个实例)才能直接被调用。

>>> class MyClass(object):
        def myNoActionMethod(self):
            pass
>>> mc=MyClass()
>>> mc.myNoActionMethod()


4.查看类的属性
两种方法,使用内建函数dir()或者是查看类的特殊属性__dict__,dir()返回的是所有的类属性的一个名字列表,而__dict__返回的是一个字典,键是属性名,值是属性的数据值。


示例:
>>> class MyClass(object):
        version=1.0
        def func(self):
            pass


>>> dir(MyClass)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'func', 'version']


>>> MyClass.__dict__
dict_proxy({'__module__': '__main__', 'version': 1.0, 'func': <function func at 0x020D23F0>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None})


5. 类的特殊属性
__name__、__doc__、__bases__、__module__、__dict__、__class__是所有类都具备的特殊类属性。

__dict__:
属性包含一个字典,由类的数据属性组成。访问一个类属性的时候,Python 解释器将会搜索字典以得到需要的属性。如果在__dict__中没有找到,将会在基类的字典中进行搜索,采用“深度优先搜索”顺序。

__module__:
这个属性说明了这个类是位于哪个模块中的,python 支持模块间的类继承,如
>>> MyClass.__module__
'__main__'


说明MyClass这个类是在__main__模块中的,如果将这个类定义到别的模块中,那么__module__存储的就是这个类所在的模块。如下:


>>> from ClassModule import MyModule
>>> MyModule
<class 'ClassModule.MyModule'>
>>> MyModule.__module__
'ClassModule'
>>> 

__bases__:对任何类,它是一个包含其父类的集合的元组,只包含直接父类。



(4)实例

实例化一个类就像调用一个函数一样,不需要new等关键字,如
myClass=MyClass()
类的__init__()和__del__()方法:
__init__()是类的初始化方法,也相当于类的构造方法,因为它可以指定类的参数,但是它确实是一个类的初始化方法,毕竟类的实例的创建工作,不是由__init__()来做的。若在自定义的类中没有定义__init__()方法,那么这个方法依然会被调用,但是没有做任何的工作,如果定义了这个方法,那么就覆盖了默认的这个方法,这个方法就会被调用,做你想让它做的事。
__del__()方法是python类中的析构方法,类似于c++中的析构方法,但不同的是,这个函数要直到该实例对象所有的引用都被清除掉后才会执行。


示例:
#类的实例的跟踪计数
class MyClass(object):
    count=0                 #静态成员变量,被所有的实例所共享


    def __init__(self):
        MyClass.count+=1    #访问类的数据属性,一定要加上命名空间,否则访问出错啊


    def __del__(self):
        MyClass.count-=1


    def howMany(self):
        return MyClass.count


>>> a=MyClass()
>>> b=MyClass()
>>> c=MyClass()   #注意,这里生成了3个类的实例,每一个实例只有一个引用,所以删除掉这个引用
		  #之后,__del__()方法就会执行了
>>> MyClass.count
3
>>> a.howMany()
3
>>> del a
>>> MyClass.count
2
>>> del c
>>> del b
>>> MyClass.count
0


(5)实例属性和类属性
类属性包括两种:数据属性和方法属性

实例属性只包括数据属性,方法属性是属于类属性中的,实例属性的数据属性也包括两种:类属性中的数据属性和自定义的数据属性

实例仅拥有数据属性(方法严格来说是类属性),实例的数据属性只是与某个类的实例相关联的数据值,并且可以通过句点属性标识法来访问。这些值独立于其它实例或类。当一个实例被释放后,它的属性
同时也被清除了。

python能够在“运行时”创建实例属性。构造器__init()__是设置这些属性的关键点之一。

动态的只是数据属性,方法属性还是用的类中的方法属性,这也是类和实例唯一有关系的地方。


python的这种特性让我一时难以接受,如果这样可以的话,那么我想问一句:这还是面向对象吗?类还是实例的“蓝本”吗?实例具有的属性,类竟然不具有,这有点像用同一个模具创出来的东西,虽然大体上看起来很像,但是总会有那么几个小小的细节是不一样的,俗话说的好,没有两片相同的叶子。python这样的特性,好像是更加的具有哲理,更加的符合常理了。不由得惊叹。。。。。。这也颠覆了多年java和c++培养起来的面向对象的概念。。。。。。。但是应用这种特性也要格外的小心,不然会变得很乱。。。。。

__init__()方法是初始化实例的,所以将实例属性放到这个地方来进行初始化,是最合适不过的了。同时可以在__init__()方法中传入默认的参数,那么在实例化类时,就可以不传递这些参数,而使用默认的值了,如下:

class AttrClass(object):


    def __init__(self,name,age=23,sex='male'):
        self.name=name
        self.age=age
        self.sex=sex      #这里使用self表示当前实例的数据属性,不用在类中进行声明就可以使用
        
    def show(self):
        print self.name, self.age, self.sex


    
>>> suo=AttrClass('suo')
>>> suo.show()
suo 23 male
>>> piao=AttrClass('piao',21,'female')
>>> piao.show()
piao 21 female
>>> 

实例的dir()和__dict__的区别:
__dict__只显示实例属性,即只显示实例的数据属性,而dir()显示类属性和实例属性,即显示实例所属类中的数据属性和方法属性,也显示实例中的数据属性。


(6)内建类型
内建类型也属于类,也有属性,不过内建类型的实例没有__dict__属性,内建类型就是complex、int、float等


(7)类属性和实例属性的区别
类属性说的是类内定义的数据属性(静态)和方法,而实例属性只包括“动态”添加到实例中的数据属性。

类属性仅是与类相关的数据值,和实例属性不同,类属性和实例无关。

类和实例都是名字空间。类是类属性的名字空间,实例则是实例属性的。

类属性可通过类或实例来访问。类属性就好像java中的静态成员变量。

当通过实例来访问类属性的话,会首先在实例属性中找这个属性,如果没找到才会去类属性中找,如果还没找到,那么就到基类中去找

注意,如果要更新类属性的值,只能通过类引用类属性才能更新,如果通过实例去更新的话,只会对这个实例生成一个新的实例属性,这个实例属性的名字和类属性的名字是相同的,这样的话,就遮蔽了实例对类属性的访问,更改的也只是实例名字空间内的这个属性,而不是类域的这个属性,只能显示的del掉这个实例属性之后,才能正常的通过实例来访问类属性,可以通过查看实例的__dict__变量来查看当前实例的实例属性,如下:


>>> class C(object):
	version=1.0    #类属性


	
>>> C.version    #通过类名访问
1.0
>>> c=C()
>>> c.version   #通过实例访问
1.0
>>> c.version=2.0   #想通过实例更改类属性
>>> c.version       #但是只是为这个实例多生成了一个实例属性,并没有更改类属性
2.0
>>> C.version
1.0
>>> c.__dict__
{'version': 2.0}
>>> del c.version   #删除掉这个实例属性之后,才可以正常的通过实例来访问类属性
>>> c.version
1.0
>>> C.version+=1
>>> C.version
2.0
>>> c.version
2.0
>>> c.__dict__
{}
>>> 


(8)绑定和方法调用

方法仅仅是类内部定义的函数。(这意味着方法是类属性而不是实例属性)。

方法只有在其所属的类拥有实例时,才能被调用。当存在一个实例时,方法才被认为是绑定到那个实例了。没有实例时方法就是未绑定的。

任何一个方法定义中的第一个参数都是变量self,它表示调用此方法的实例对象。也就是代表这些方法所绑定的实例。这个self是必须要作为第一个参数传递的,它表示要将哪个实例和类方法进行绑定。


(9)静态方法和类方法

类方法和静态方法的区别我还没有弄清楚。。。。。不过类方法和静态方法都可以通过类名来调用。

类方法,需要类而不是实例作为第一个参数,它是由解释器传给方法。类不需要特别地命名, 类似self,不过很多人使用cls 作为变量名字。

示例:
# -*- coding: cp936 -*-
class AttrClass(object):


    def __init__(self,name,age=23,sex='male'):
        self.name=name
        self.age=age
        self.sex=sex
        
    def show(self):
        print self.name, self.age, self.sex


    #使用staticmethod()内建方法,将一个方法设置为静态方法
    def staticFoo1():
        print 'calling static method foo1()'
    staticFoo1=staticmethod(staticFoo1)


    #使用classmethod()内建方法,将一个方法设置为类方法
    def classMethod1(cls):
        print 'calling class method1'
    classMethod1=classmethod(classMethod1)
    
    #使用修饰符将一个方法设置为静态方法
    @staticmethod    
    def staticFoo2():
        print 'calling static method foo2()'


    #使用修饰符将一个方法设置为类方法
    @classmethod
    def classMethod2(cls):
        print 'calling class method2'


(10)继承
一个子类可以继承它的基类的任何属性,不管是数据属性还是方法。
文档字符串对类,函数/方法,还有模块来说都是唯一的,所以特殊属性__doc__不会从基类中继承过来
# -*- coding: cp936 -*-
class AddrBookEntry(object):
    'address book entry class'

    '''
    (1)这个__init__方法不是类的构造方法,而是一个在返回类实例之前的一个初始化方法,
       会被隐式的调用
    (2)方法的第一个参数为self,它代表实例对象本身,这个参数不用显示的传递进来,是自动传入的
    '''
    def __init__(self,nm,ph):
        self.name=nm
        self.phone=ph
        print 'Created instance for: ',self.name
        
    def updatePhone(self,newph):
        'update...'
        self.phone=newph
        print 'Update phone for: ',self.name




'''
(1)这个类继承自AddrBookEntry类,父类是写在类名后的小括号中的,如果有多个父类要继承,那么就可以
把所有的父类以逗号相隔,写在括号中
(2)子类也要有这个__init__方法,并且在子类的__init__方法中,要用父类的类名调用父类的__init__方法,
并且一定要显示的写上第一个参数为self
(3)子类继承了父类的所有的方法和属性
'''
class EmplAddrBookEntry(AddrBookEntry):
    'Employee Address Book Entry class extend from AddrBookEntry'
    def __init__(self,nm,ph,id,em):
        #AddrBookEntry.__init__(self,nm,ph)
        super(EmplAddrBookEntry,self).__init__(nm,ph)#两种调用父类方法的方法,推荐使用						#super(),因为它不需要显示的指定父类是谁
        self.empid=id
        self.email=em


    def updateEmail(self,newem):
        self.email=newem
        print 'Update e-mail address for:', self.name


(11)内建函数
issubclass(sub, sup)::给出的子类sub 确实是父类sup 的一个子类,则返回True,否则返回False
isinstance(obj1, obj2):在obj1 是类obj2 的一个实例,或者是obj2 的子类的一个实例时,返回True(反之,则为False)


(12)hasattr(), getattr(),setattr(), delattr()
当使用这些函数时,你传入你正在处理的对象作为第一个参数,但属性名,也就是这些函数的第二个参数,是这些属性的字符串名字。换句话说,在操作obj.attr 时,就相当于调用*attr(obj,'attr'....)系列函数


>>> class myClass(object):
... def __init__(self):
... self.foo = 100
...
>>> myInst = myClass()
>>> hasattr(myInst, 'foo')
True
>>> getattr(myInst, 'foo')
100
>>> hasattr(myInst, 'bar') 
False
>>> getattr(myInst, 'bar')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
getattr(myInst, 'bar')
AttributeError: myClass instance has no attribute 'bar'
>>> getattr(c, 'bar', 'oops!')
'oops!'
>>> setattr(myInst, 'bar', 'my attr')
>>> dir(myInst)
['__doc__', '__module__', 'bar', 'foo']
>>> getattr(myInst, 'bar') # same as myInst.bar #等同于 myInst.bar
'my attr'
>>> delattr(myInst, 'foo')
>>> dir(myInst)
['__doc__', '__module__', 'bar']
>>> hasattr(myInst, 'foo')
False


(13)input()和raw_input()的区别
input 不同于raw_input(),因为raw_input()总是以字符串的形式,逐字地返回用
户的输入。input()履行相同的的任务;而且,它还把输入作为python 表达式进行求值。这意味着
input()返回的数据是对输入表达式求值的结果:一个python 对象



未完待续。。。。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值