python基础学习(七)——面向对象进阶

面向对象高级语法部分

经典类vs新式类

把下面代码用python2 python3都执行一下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

#_*_coding:utf-8_*_

 

 

class A:

    def __init__(self):

        self.n = 'A'

 

class B(A):

    # def __init__(self):

    #     self.n = 'B'

    pass

 

class C(A):

    def __init__(self):

        self.n = 'C'

 

class D(B,C):

    # def __init__(self):

    #     self.n = 'D'

    pass

 

obj = D()

 

print(obj.n)

classical vs new style

·        经典类:深度优先

·        新式类:广度优先

·        super()用法

抽象接口

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

import abc

 

class Alert(object):

    '''报警基类'''

    __metaclass__ = abc.ABCMeta

 

    @abc.abstractmethod

    def send(self):

        '''报警消息发送接口'''

        pass

 

 

 

class MailAlert(Alert):

    pass

 

 

m = MailAlert()

m.send()

上面的代码仅在py2里有效,python3里怎么实现呢?

静态方法

通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法

1

2

3

4

5

6

7

8

9

10

11

12

13

class Dog(object):

 

    def __init__(self,name):

        self.name = name

 

    @staticmethod #把eat方法变为静态方法

    def eat(self):

        print("%s is eating" % self.name)

 

 

 

d = Dog("ChenRonghua")

d.eat()

上面的调用会出以下错误,说是eat需要一个self参数,但调用时却没有传递,没错,当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了。

1

2

3

4

Traceback (most recent call last):

  File "/Users/jieli/PycharmProjects/python基础/自动化day7面

向对象高级/静态方法.py", line 17, in <module>

    d.eat()

TypeError: eat() missing 1 required positional argument: 'self'

想让上面的代码可以正常工作有两种办法

1. 调用时主动传递实例本身给eat方法,即d.eat(d) 

2. eat方法中去掉self参数,但这也意味着,在eat中不能通过self.调用实例中的其它变量了,只是类中的一个函数,名义上归类管。

 1class Dog(object):

 2

 3     def__init__(self,name):

 4         self.name = name

 5

 6     @staticmethod

 7     defeat():

 8         print("%s is eating" %(self.name)

 9

10

11

12 d = Dog("ChenRonghua")

13 d.eat(d),#不用传参数。

类方法  

类方法通过@classmethod装饰器实现,类方法和普通方法的区别是,类方法只能访问类变量,不能访问实例变量

1

2

3

4

5

6

7

8

9

10

11

12

class Dog(object):

    def __init__(self,name):

        self.name = name

 

    @classmethod

    def eat(self):

        print("%s is eating" % self.name)

 

 

 

d = Dog("ChenRonghua")

d.eat()

执行报错如下,说Dog没有name属性,因为name是个实例变量,类方法是不能访问实例变量的

1

2

3

4

5

6

Traceback (most recent call last):

  File "/Users/jieli/PycharmProjects/python基础/自动化day7面

向对象高级/类方法.py", line 16, in <module>

    d.eat()

  File "/Users/jieli/PycharmProjects/python基础/自动化day7面

向对象高级/类方法.py", line 11, in eat

    print("%s is eating" % self.name)

AttributeError: type object 'Dog' has no attribute 'name'

此时可以定义一个类变量,也叫name,看下执行效果

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

class Dog(object):

    name = "我是类变量"

    def __init__(self,name):

        self.name = name

 

    @classmethod

    def eat(self):

        print("%s is eating" % self.name)

 

 

 

d = Dog("ChenRonghua")

d.eat()

 

 

#执行结果

 

我是类变量 is eating

属性方法  

属性方法的作用就是通过@property把一个方法变成一个静态属性

1

2

3

4

5

6

7

8

9

10

11

12

class Dog(object):

 

    def __init__(self,name):

        self.name = name

 

    @property

    def eat(self):

        print(" %s is eating" %self.name)

 

 

d = Dog("ChenRonghua")

d.eat()

调用会出以下错误,NoneType is not callable, 因为eat此时已经变成一个静态属性了,不是方法了,想调用已经不需要加()号了,直接d.eat就可以了

1

2

3

4

5

Traceback (most recent call last):

 ChenRonghua is eating

  File "/Users/jieli/PycharmProjects/python基础/自动化day7面

向对象高级/属性方法.py", line 16, in <module>

    d.eat()

TypeError: 'NoneType' object is not callable

正常调用如下

1

2

3

4

5

d = Dog("ChenRonghua")

d.eat

 

输出

 ChenRonghua is eating

好吧,把一个方法变成静态属性有什么卵用呢?既然想要静态变量,那直接定义成一个静态变量不就得了么?well, 以后你会需到很多场景是不能简单通过定义静态属性来实现的,比如,你想知道一个航班当前的状态,是到达了、延迟了、取消了、还是已经飞走了,想知道这种状态你必须经历以下几步:

1. 连接航空公司API查询

2. 对查询结果进行解析 

3. 返回结果给你的用户

因此这个status属性的值是一系列动作后才得到的结果,所以你每次调用时,其实它都要经过一系列的动作才返回你结果,但这些动作过程不需要用户关心(数据传输时,首先从航空公司接受数据,然后将数据传给每个用户,第一步不需要用户关心,所以直接用静态属性获取即可,然后用户直接用数据),用户只需要调用这个属性就可以,明白了么?

航班动态:

class Flight(object):

    def__init__(self,name):

        self.flight_name = name


    def checking_status(self):

        print("checking flight %s status " % self.flight_name)

        return  1

 

    @property

    def flight_status(self):

        status = self.checking_status()

        ifstatus == 0 :

            print("flight got canceled...")

        elifstatus == 1 :

            print("flight is arrived...")

        elifstatus == 2:

            print("flight has departured already...")

        else:

            print("cannot confirm the flightstatus...,please check later")


f = Flight("CA980")

f.flight_status

cool , 那现在我只能查询航班状态,既然这个flight_status已经是个属性了,那我能否给它赋值呢?试试吧

1

2

3

f = Flight("CA980")

f.flight_status

f.flight_status =  2

输出,说不能更改这个属性,我擦。。。。,怎么办怎么办。。。 

1

2

3

4

5

6

checking flight CA980 status

flight is arrived...

Traceback (most recent call last):

  File "/Users/jieli/PycharmProjects/python基础/自动化day7面

向对象高级/属性方法.py", line 58, in <module>

    f.flight_status =  2

AttributeError: can't set attribute

当然可以改,不过需要通过@proerty.setter装饰器再装饰一下,此时你需要写一个新方法,对这个flight_status进行更改。

class Flight(object):

    def__init__(self,name):

        self.flight_name = name


    def checking_status(self):

        print("checking flight %s status " % self.flight_name)

        return  1


    @property

    def flight_status(self):

        status = self.checking_status()  #一般的属性可以在属性方法中使用。

        ifstatus == 0 :

            print("flight got canceled...")

        elifstatus == 1 :

            print("flight is arrived...")

        elifstatus == 2:

            print("flight has departured already...")

        else:

            print("cannot confirm the flightstatus...,please check later")

   

    @flight_status.setter #修改

    def flight_status(self,status):

        status_dic = {

            0 : "canceled",

            1 :"arrived",

            2 : "departured"

        }

        print("\033[31;1mHas changed the flightstatus to \033[0m",status_dic.get(status))

 

    @flight_status.deleter  #删除

    def flight_status(self):

        print("status got removed...")

 

f = Flight("CA980")

f.flight_status

f.flight_status=  2 #触发@flight_status.setter

del f.flight_status #触发@flight_status.deleter

注意以上代码里还写了一个@flight_status.deleter,是允许可以将这个属性删除 

 #!/usr/bin/env python
# _*_ UTF-8 _*_


class people(object):   #新式类
    def __init__(self, name):
        self.name =name

    @property
    def eat(self):
        print("%s is eating %s" %(self.name, 'ddd'))
    #为属性方法传参数的方式:
    @eat.setter
    def eat(self, food):
        self.__food=food
        print("set to food:", food)
    #删除属性方法:
    @eat.deleter
    def eat(self):
        del self.__food
        print("删完了~")

d=people("chen")
#d.eat
d.eat="baozi"

类的特殊成员方法

1. __doc__  表示类的描述信息

1

2

3

4

5

6

7

8

class Foo:

    """ 描述类信息,这是用于看片的神奇 """

 

    def func(self):

        pass

 

print Foo.__doc__

#输出:类的描述信息

2. __module__  __class__ 

__module__ 表示当前操作的对象在那个模块

__class__    表示当前操作的对象的类是什么

class C:

 

    def__init__(self):

        self.name = 'wupeiqi'

from lib.aa import C

 

obj = C()

print obj.__module__  # 输出 lib.aa,即:输出模块

print obj.__class__      # 输出 lib.aa.C,即:输出类

3. __init__ 构造方法,通过类创建对象时,自动触发执行。

4.__del__

 析构方法,当对象在内存中被释放时,自动触发执行。

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的

 5. __call__ 对象后面加括号,触发执行。

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者()()

classDistanceForm(object):

  def__init__(self, origin):

    self.origin =origin

    print"origin :"+str(origin)

  def__call__(self, x):

    print"x :"+str(x)

p =DistanceForm(100)

p(2000)

类调用是用构造函数__init__()

对象调用是用call函数__call__()

1

2

3

4

5

6

7

8

9

10

11

12

class Foo:

 

    def __init__(self):

        pass

     

    def __call__(self, *args, **kwargs):

 

        print '__call__'

 

 

obj = Foo() # 执行 __init__

obj()       # 执行 __call__

6. __dict__ 查看类或对象中的所有成员 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

class Province:

 

    country = 'China'

 

    def __init__(self, name, count):

        self.name = name

        self.count = count

 

    def func(self, *args, **kwargs):

        print 'func'

 

# 获取类的成员,即:静态字段、方法、

print Province.__dict__

# 输出:{'country': 'China', '__module__': '__main__', 'func':

 <function func at 0x10be30f50>, '__init__':

<function __init__ at 0x10be30ed8>, '__doc__': None}

 

obj1 = Province('HeBei',10000)

print obj1.__dict__

# 获取 对象obj1 的成员

# 输出:{'count': 10000, 'name': 'HeBei'}

 

obj2 = Province('HeNan', 3888)

print obj2.__dict__

# 获取 对象obj1 的成员

# 输出:{'count': 3888, 'name': 'HeNan'}

7.__str__ 如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值。

1

2

3

4

5

6

7

8

9

class Foo:

 

    def __str__(self):

        return 'alex li'

 

 

obj = Foo()

print obj

# 输出:alex li

8.__getitem____setitem____delitem__

用于索引操作,如字典。以上分别表示获取、设置、删除数据

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

class Foo(object):

 

    def __getitem__(self, key):

        print('__getitem__',key)

 

    def __setitem__(self, key, value):

        print('__setitem__',key,value)

 

    def __delitem__(self, key):

        print('__delitem__',key)

 

 

obj = Foo()

 

result = obj['k1']      # 自动触发执行 __getitem__

obj['k2'] = 'alex'   # 自动触发执行 __setitem__

del obj['k1']   

9. __new__ \ __metaclass__

1

2

3

4

5

6

7

8

class Foo(object):

 

 

    def __init__(self,name):

        self.name = name

 

 

f = Foo("alex")

上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象

如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的构造方法创建。

1

2

3

4

print type(f) # 输出:<class '__main__.Foo'>    

表示,obj 对象由Foo类创建

print type(Foo) # 输出:<type 'type'>             

表示,Foo类对象由 type 类创建

所以,f对象是Foo类的一个实例Foo类对象是 type 类的一个实例,即:Foo类对象是通过type类的构造方法创建。

那么,创建类就可以有两种方式:

a). 普通方式 

1

2

3

4

class Foo(object):

  

    def func(self):

        print 'hello alex'

b). 特殊方式

1

2

3

4

5

6

7

def func(self):

    print 'hello wupeiqi'

  

Foo = type('Foo',(object,), {'func': func})

#type第一个参数:类名

#type第二个参数:当前类的基类

#type第三个参数:类的成员

def func(self):

    print("hello %s"%self.name)

 

def__init__(self,name,age):

    self.name = name

    self.age = age

Foo = type('Foo',(object,),{'func':func,'__init__':__init__})

 

f = Foo("jack",22)

f.func()

class Foo(object):
    def __init__(self, name):
        self.name = name
        print("Foo ---init__")

    def __new__(cls, *args, **kwargs):   #类实例化是先走的new,然后new触发init,进而实例化类。
        print("Foo --new--")
        return object.__new__(cls)   #重构new函数后,需要继承父类的new方法,然后return即可。

f=Foo()

So ,孩子记住,类是由 type 类实例化产生

那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?

答:类中有一个属性 __metaclass__,其用来表示该类由来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看创建的过程。

python基础学习(七)——面向对象进阶

 1class MyType(type):

 2     def__init__(self,*args,**kwargs):

 3

 4         print("Mytype __init__",*args,**kwargs)

 5

 6     def__call__(self, *args, **kwargs):

 7         print("Mytype __call__", *args, **kwargs)

 8         obj = self.__new__(self)

 9         print("obj ",obj,*args, **kwargs)

10        print(self)

11        self.__init__(obj,*args, **kwargs)

12        return obj

13

14     def__new__(cls, *args, **kwargs):

15        print("Mytype __new__",*args,**kwargs)

16        return type.__new__(cls,*args, **kwargs)

17

18print('here...')

19class Foo(object,metaclass=MyType):

20

21

22     def__init__(self,name):

23        self.name = name

24

25        print("Foo __init__")

26

27     def__new__(cls, *args, **kwargs):

28        print("Foo __new__",cls,*args, **kwargs)

29        return object.__new__(cls)

30

31 f = Foo("Alex")

32print("f",f)

33print("fname",f.name)

 类的生成调用顺序依次是 __new__ --> __init__ --> __call__

 metaclass 详解文章:http://*.com/questions/100003/what-is-a-metaclass-in-python得票最高那个答案写的非常好

反射

通过字符串映射或修改程序运行时的状态、属性、方法, 有以下4个方法:

Hasattr()

def getattr(object, name,default=None):# known special case of getattr

    """

    getattr(object, name[, default]) ->value

   

    Get a named attribute from an object;getattr(x, 'y') is equivalent to x.y.

    When a default argument is given, it isreturned when the attribute doesn't

    exist; without it, an exception is raisedin that case.

    """

    pass

判断object中有没有一个name字符串对应的方法或属性

def setattr(x, y, v):# real signature unknown; restored from __doc__

    """

    Sets the named attribute on the givenobject to the specified value.

   

    setattr(x, 'y', v) is equivalent to ``x.y =v''

def delattr(x, y):# real signature unknown; restored from __doc__

    """

    Deletes the named attribute from the givenobject.

   

    delattr(x, 'y') is equivalent to ``delx.y''

    """


class Foo(object):

 

    def__init__(self):

        self.name = 'wupeiqi'

 

    def func(self):

        return'func'

 

obj = Foo()

 

# #### 检查是否含有成员 ####

hasattr(obj, 'name')

hasattr(obj, 'func')

 

# #### 获取成员 ####

getattr(obj, 'name')

getattr(obj, 'func')

 

# #### 设置成员 ####

setattr(obj, 'age', 18)

setattr(obj, 'show', lambda num: num + 1)

 

# #### 删除成员 ####

delattr(obj, 'name')

delattr(obj, 'func')

 #!/usr/bin/env python
# _*_ UTF-8 _*_

def bulk(self):
    print("is yelling......")

class Dog(object):
    def __init__(self, name):
        self.name = name

    def eat(self):
        print("%s is eating", self.name)


d=Dog("NiuHanYang")
choice = input(">>:").strip()

if hasattr(d, choice):  #此为反射应用。
    func = getattr(d, choice)
    func("chenronghua")
    delattr(d, choice)  #删除d对象中的choice方法。
elif:
    setattr(d, choice, bulk)   #即在d对象中装入chioce方法,方法的内容是bulk。
    d.bulk(d)



#hasattr:判断一个对象里是否有对应字符串的方法映射;
#getattr:根据字符串去获取一个对象中的对应字符串方法的内存地址;
#setattr:根据字符串装载一个方法到对象中。
#delattr: 删除对象中的属性。

动态导入模块:

 python基础学习(七)——面向对象进阶

1

2

3

4

import importlib

 

__import__('import_lib.metaclass') #这是解释器自己内部用的

#importlib.import_module('import_lib.metaclass') #与上面这句效果一样,

官方建议用这个

异常处理 

参考http://www.cnblogs.com/wupeiqi/articles/5017742.html   

 面向对象基础

基础内容介绍详见一下两篇博文:

·        面向对象初级篇

·        面向对象进阶篇

其他相关

一、isinstance(obj,cls)

 检查是否obj是否是类 cls 的对象

1

2

3

4

5

6

class Foo(object):

    pass

 

obj = Foo()

 

isinstance(obj, Foo)

二、issubclass(sub,super)

检查sub类是否是 super 类的派生类

1

2

3

4

5

6

7

class Foo(object):

    pass

 

class Bar(Foo):

    pass

 

issubclass(Bar, Foo)

三、异常处理

1、异常基础

在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户看见大黄页!!!

1

2

3

4

try:

    pass

except Exception,ex:

    pass

需求:将用户输入的两个数字相加

自定义异常:

Class AlexExceptionException):

     Def __init__self, msg:

          Self.message = msg

     Def __str__(self):

          Return self.message

raise触发异常:

Try

Raise AlexException(‘数据库连不上’)

ExceptAlexException as e:

    Printe

while True:

    num1 = raw_input('num1:')

    num2 = raw_input('num2:')

    try:

        num1 = int(num1)

        num2 = int(num2)

        result = num1 + num2

    except Exception, e:

        print'出现异常,信息如下:'

        print e

except IndexErroras e:

    print(“列表操作错误”,e)

2、异常种类

python中的异常种类非常多,每个异常专门用于处理某一项异常!!!

AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x

IOError 输入/输出异常;基本上是无法打开文件

ImportError 无法引入模块或包;基本上是路径问题或名称错误

IndentationError 语法错误(的子类) ;代码没有正确对齐

IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]

KeyError 试图访问字典里不存在的键

KeyboardInterruptCtrl+C被按下

NameError 使用一个还未被赋予对象的变量

SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)

TypeError 传入对象类型与要求的不符合

UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,

导致你以为正在访问它

ValueError 传入一个调用者不期望的值,即使值的类型是正确的

ArithmeticError

AssertionError

AttributeError

BaseException

BufferError

BytesWarning

DeprecationWarning

EnvironmentError

EOFError

Exception

FloatingPointError

FutureWarning

GeneratorExit

ImportError

ImportWarning

IndentationError

IndexError

IOError

KeyboardInterrupt

KeyError

LookupError

MemoryError

NameError

NotImplementedError

OSError

OverflowError

PendingDeprecationWarning

ReferenceError

RuntimeError

RuntimeWarning

StandardError

StopIteration

SyntaxError

SyntaxWarning

SystemError

SystemExit

TabError

TypeError

UnboundLocalError

UnicodeDecodeError

UnicodeEncodeError

UnicodeError

UnicodeTranslateError

UnicodeWarning

UserWarning

ValueError

Warning

ZeroDivisionError

dic = ["wupeiqi", 'alex']

try:

    dic[10]

except IndexError, e:

    print e

dic = {'k1':'v1'}

try:

    dic['k20']

except KeyError, e:

    print e

s1 = 'hello'

try:

    int(s1)

except ValueError, e:

    print e

对于上述实例,异常类只能用来处理指定的异常情况,如果非指定异常则无法处理。

1

2

3

4

5

6

7

# 未捕获到异常,程序直接报错

 

s1 = 'hello'

try:

    int(s1)

except IndexError,e:

    print e

所以,写程序时需要考虑到try代码块中可能出现的任意异常,可以这样写:

1

2

3

4

5

6

7

8

9

s1 = 'hello'

try:

    int(s1)

except IndexError,e:

    print e

except KeyError,e:

    print e

except ValueError,e:

    print e

万能异常python的异常中,有一个万能异常:Exception,他可以捕获任意异常,即:

1

2

3

4

5

s1 = 'hello'

try:

    int(s1)

except Exception,e:

    print e

接下来你可能要问了,既然有这个万能异常,其他异常是不是就可以忽略了!

答:当然不是,对于特殊处理或提醒的异常需要先定义,最后定义Exception来确保程序正常运行。

1

2

3

4

5

6

7

8

9

s1 = 'hello'

try:

    int(s1)

except KeyError,e:

    print '键错误'

except IndexError,e:

    print '索引错误'

except Exception, e:

    print '错误'

3、异常其他结构

1

2

3

4

5

6

7

8

9

10

11

12

try:

    # 主代码块

    pass

except KeyError,e:

    # 异常时,执行该块

    pass

else:

    # 主代码块执行完,执行该块

    pass

finally:

    # 无论异常与否,最终执行该块

    pass

4、主动触发异常

1

2

3

4

try:

    raise Exception('错误了。。。')

except Exception,e:

    print e

5、自定义异常

1

2

3

4

5

6

7

8

9

10

11

12

class WupeiqiException(Exception):

 

    def __init__(self, msg):

        self.message = msg

 

    def __str__(self):

        return self.message

 

try:

    raise WupeiqiException('我的异常')

except WupeiqiException,e:

    print e

6、断言

1

2

3

4

5

# assert 条件

 

assert 1 == 1

 

assert 1 == 2

四、反射

python中的反射功能是由以下四个内置函数提供:hasattrgetattrsetattrdelattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

class Foo(object):

 

    def __init__(self):

        self.name = 'wupeiqi'

 

    def func(self):

        return 'func'

 

obj = Foo()

 

# #### 检查是否含有成员 ####

hasattr(obj, 'name')

hasattr(obj, 'func')

 

# #### 获取成员 ####

getattr(obj, 'name')

getattr(obj, 'func')

 

# #### 设置成员 ####

setattr(obj, 'age', 18)

setattr(obj, 'show', lambda num: num + 1)

 

# #### 删除成员 ####

delattr(obj, 'name')

delattr(obj, 'func')

详细解析:

当我们要访问一个对象的成员时,应该是这样操作:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

class Foo(object):

 

    def __init__(self):

        self.name = 'alex'

 

    def func(self):

        return 'func'

 

obj = Foo()

 

# 访问字段

obj.name

# 执行方法

obj.func()

python基础学习(七)——面向对象进阶

那么问题来了?

a、上述访问对象成员的 name func 是什么? 

答:是变量名

bobj.xxx 是什么意思? 

答:obj.xxx 表示去obj中或类中寻找变量名 xxx,并获取对应内存地址中的内容。

c、需求:请使用其他方式获取obj对象中的name变量指向内存中的值 “alex”

class Foo(object):

 

    def__init__(self):

        self.name = 'alex'

 

# 不允许使用 obj.name

obj = Foo()

答:有两种方式,如下:

class Foo(object):

 

    def__init__(self):

        self.name = 'alex'

 

    def func(self):

        return'func'

 

# 不允许使用 obj.name

obj = Foo()

 

print obj.__dict__['name']

class Foo(object):

 

    def__init__(self):

        self.name = 'alex'

 

    def func(self):

        return'func'

 

# 不允许使用 obj.name

obj = Foo()

 

print getattr(obj, 'name')

d、比较三种访问方式

·        obj.name

·        obj.__dict__['name']

·        getattr(obj, 'name')

答:第一种和其他种比,...
      第二种和第三种比,...

#!/usr/bin/envpython

#coding:utf-8

from wsgiref.simple_server import make_server

 

class Handler(object):

 

    def index(self):

        return'index'

 

    def news(self):

        return'news'


def RunServer(environ, start_response):

    start_response('200 OK', [('Content-Type', 'text/html')])

    url = environ['PATH_INFO']

    temp = url.split('/')[1]

    obj = Handler()

    is_exist = hasattr(obj, temp)

    if is_exist:

        func = getattr(obj, temp)

        ret = func()

        return ret

    else:

        return'404 not found'

 

if__name__ == '__main__':

    httpd = make_server('', 8001, RunServer)

    print"Serving HTTP on port 8000..."

    httpd.serve_forever()

结论:反射是通过字符串的形式操作对象相关的成员。一切事物都是对象!!!

#!/usr/bin/envpython

# -*- coding:utf-8-*-

 

import sys


def s1():

    print's1'


def s2():

    print's2'


this_module =sys.modules[__name__]

 

hasattr(this_module,'s1')

getattr(this_module,'s2')


类也是对象

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

class Foo(object):

 

    staticField = "old boy"

 

    def __init__(self):

        self.name = 'wupeiqi'

 

    def func(self):

        return 'func'

 

    @staticmethod

    def bar():

        return 'bar'

 

print getattr(Foo, 'staticField')

print getattr(Foo, 'func')

print getattr(Foo, 'bar')

模块也是对象

#!/usr/bin/envpython

# -*- coding:utf-8-*-

 

def dev():

    return'dev'

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

#!/usr/bin/env python

# -*- coding:utf-8 -*-

 

"""

程序目录:

    home.py

    index.py

 

当前文件:

    index.py

"""

 

 

import home as obj

 

#obj.dev()

 

func = getattr(obj, 'dev')

func() 

设计模式

一、单例模式

单例,顾名思义单个实例。

学习单例之前,首先来回顾下面向对象的内容:

python的面向对象由两个非常重要的两个东西组成:类、实例

面向对象场景一:

如:创建三个游戏人物,分别是:

·        苍井井,女,18,初始战斗力1000

·        东尼木木,男,20,初始战斗力1800

·        波多多,女,19,初始战斗力2500

######################  定义类 #####################

class Person:

 

    def__init__(self, na, gen, age,fig):

        self.name = na

        self.gender = gen

        self.age = age

        self.fight =fig

 

    def grassland(self):

        """注释:草丛战斗,消耗200战斗力"""

 

        self.fight = self.fight - 200

 

######################  创建实例 #####################

 

cang = Person('苍井井', '女', 18, 1000)    # 创建苍井井角色

dong = Person('东尼木木', '男', 20, 1800)  # 创建东尼木木角色

bo = Person('波多多', '女', 19, 2500)      # 创建波多多角色

面向对象场景二:

如:创建对数据库操作的公共类

·        

·        

·        

·        

# #### 定义类 ####

 

class DbHelper(object):

 

    def__init__(self):

        self.hostname = '1.1.1.1'

        self.port = 3306

        self.password = 'pwd'

        self.username = 'root'

 

    def fetch(self):

        # 连接数据库

        # 拼接sql语句

        # 操作

        pass

 

    def create(self):

        # 连接数据库

        # 拼接sql语句

        # 操作

        pass

 

    def remove(self):

        # 连接数据库

        # 拼接sql语句

        # 操作

        pass

 

    def modify(self):

        # 连接数据库

        # 拼接sql语句

        # 操作

        pass

 

# #### 操作类 ####

 

db = DbHelper()

db.create()

实例:结合场景二实现Web应用程序

#!/usr/bin/envpython

#coding:utf-8

from wsgiref.simple_server import make_server

 

 

class DbHelper(object):

 

    def__init__(self):

        self.hostname = '1.1.1.1'

        self.port = 3306

        self.password = 'pwd'

        self.username = 'root'

 

    def fetch(self):

        # 连接数据库

        # 拼接sql语句

        # 操作

        return'fetch'

 

    def create(self):

        # 连接数据库

        # 拼接sql语句

        # 操作

        return'create'

 

    def remove(self):

        # 连接数据库

        # 拼接sql语句

        # 操作

        return'remove'

 

    def modify(self):

        # 连接数据库

        # 拼接sql语句

        # 操作

        return'modify'

 

 

class Handler(object):

 

    def index(self):

        # 创建对象

        db = DbHelper()

        db.fetch()

        return'index'

 

    def news(self):

        return'news'

 

 

def RunServer(environ, start_response):

    start_response('200 OK', [('Content-Type', 'text/html')])

    url = environ['PATH_INFO']

    temp = url.split('/')[1]

    obj = Handler()

    is_exist = hasattr(obj, temp)

    if is_exist:

        func = getattr(obj, temp)

        ret = func()

        return ret

    else:

        return'404 not found'

 

if__name__ == '__main__':

    httpd = make_server('', 8001, RunServer)

    print"Serving HTTP on port 8001..."

    httpd.serve_forever()

对于上述实例,每个请求到来,都需要在内存里创建一个实例,再通过该实例执行指定的方法。

那么问题来了...如果并发量大的话,内存里就会存在非常多功能上一模一样的对象。存在这些对象肯定会消耗内存,对于这些功能相同的对象可以在内存中仅创建一个,需要时都去调用,也是极好的!!!

铛铛铛铛 铛铛铛铛铛,单例模式出马,单例模式用来保证内存中仅存在一个实例!!!

通过面向对象的特性,构造出单例模式:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

# ########### 单例类定义 ###########

class Foo(object):

 

    __instance = None

 

    @staticmethod

    def singleton():

        if Foo.__instance:

            return Foo.__instance

        else:

            Foo.__instance = Foo()

            return Foo.__instance

 

# ########### 获取实例 ###########

obj = Foo.singleton()

对于Python单例模式,创建对象时不能再直接使用:obj = Foo(),而应该调用特殊的方法:obj =Foo.singleton()

#!/usr/bin/envpython

#coding:utf-8

from wsgiref.simple_server import make_server

 

# ########### 单例类定义 ###########

class DbHelper(object):

 

    __instance = None

 

    def__init__(self):

        self.hostname = '1.1.1.1'

        self.port = 3306

        self.password = 'pwd'

        self.username = 'root'

 

    @staticmethod

    def singleton():

        ifDbHelper.__instance:

            returnDbHelper.__instance

        else:

            DbHelper.__instance =DbHelper()

            returnDbHelper.__instance

 

    def fetch(self):

        # 连接数据库

        # 拼接sql语句

        # 操作

        pass

 

    def create(self):

        # 连接数据库

        # 拼接sql语句

        # 操作

        pass

 

    def remove(self):

        # 连接数据库

        # 拼接sql语句

        # 操作

        pass

 

    def modify(self):

        # 连接数据库

        # 拼接sql语句

        # 操作

        pass

 

 

class Handler(object):

 

    def index(self):

        obj = DbHelper.singleton()

        printid(single)

        obj.create()

        return'index'

 

    def news(self):

        return'news'

 

 

def RunServer(environ, start_response):

    start_response('200 OK', [('Content-Type', 'text/html')])

    url = environ['PATH_INFO']

    temp = url.split('/')[1]

    obj = Handler()

    is_exist = hasattr(obj, temp)

    if is_exist:

        func = getattr(obj, temp)

        ret = func()

        return ret

    else:

        return'404 not found'

 

if__name__ == '__main__':

    httpd = make_server('', 8001, RunServer)

    print"Serving HTTP on port 8001..."

    httpd.serve_forever()

总结:单利模式存在的目的是保证当前内存中仅存在单个实例,避免内存浪费!!!