17、python面向对象进阶

面向对象进阶

isinstance和issubclass

isinstance(obj,cls)检查是否obj是否是类 cls 的对象

class Foo(object):

    pass 

obj = Foo()


isinstance(obj, Foo)

issubclass(sub, super)检查sub类是否是 super 类的派生类 

class Foo(object):

    pass class Bar(Foo):

    pass

issubclass(Bar, Foo)

反射

1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。


2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

四个可以实现自省的函数

下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

def hasattr(*args, **kwargs): # real signature unknown    """

    Return whether the object has an attribute with the given name.


    This is done by calling getattr(obj, name) and catching AttributeError.

    """    pass

以下实例展示了 hasattr 的使用方法:

#!/usr/bin/python# -*- coding: UTF-8 -*- class Coordinate:

    x = 10    y = -5    z = 0 point1 = Coordinate() print(hasattr(point1, 'x'))print(hasattr(point1, 'y'))print(hasattr(point1, 'z'))print(hasattr(point1, 'no'))  # 没有该属性

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 is returned when the attribute doesn't

    exist; without it, an exception is raised in that case.

    """    pass

以下实例展示了 getattr 的使用方法:

>>>class A(object):

...    bar = 1...

>>> a = A()>>> getattr(a, 'bar')        # 获取属性 bar 值1>>> getattr(a, 'bar2')      # 属性 bar2 不存在,触发异常Traceback (most recent call last):

  File "<stdin>", line 1, in <module>AttributeError: 'A' object has no attribute 'bar2'>>> getattr(a, 'bar2', 3)    # 属性 bar2 不存在,但设置了默认值3

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

    Sets the named attribute on the given object to the specified value.


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

    """    pass

以下实例展示了 setattr() 函数的使用方法:

实例一

>>>class A(object):

...    bar = 1...

>>> a = A()>>> getattr(a, 'bar')          # 获取属性 bar 值1>>> setattr(a, 'bar', 5)      # 设置属性 bar 值>>> a.bar5

实例二

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

    Deletes the named attribute from the given object.


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

    """    pass

以下实例展示了 delattr 的使用方法:实例一class Coordinate:

    x = 10    y = -5    z = 0 point1 = Coordinate()

print('x = ',point1.x)print('y = ',point1.y)print('z = ',point1.z) delattr(Coordinate, 'z') print('--删除 z 属性后--')print('x = ',point1.x)print('y = ',point1.y) # 触发错误print('z = ',point1.z)

实例二

class Foo:

    f = '类的静态变量'    def __init__(self,name,age):

        self.name=name

        self.age=age

    def say_hi(self):

        print('hi,%s'%self.name)

obj=Foo('egon',73)#检测是否含有某属性print(hasattr(obj,'name'))print(hasattr(obj,'say_hi'))#获取属性n=getattr(obj,'name')print(n)

func=getattr(obj,'say_hi')

func()print(getattr(obj,'aaaaaaaa','不存在啊')) #报错#设置属性setattr(obj,'sb',True)

setattr(obj,'show_name',lambda self:self.name+'sb')print(obj.__dict__)print(obj.show_name(obj))#删除属性delattr(obj,'age')

delattr(obj,'show_name')

delattr(obj,'show_name111')#不存在,则报错print(obj.__dict__)

实例三

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') #获取到func的地址print getattr(Foo, 'bar')

实例四

import sys

def s1():

    print 's1'def s2():

    print 's2'this_module = sys.modules[__name__]

hasattr(this_module, 's1')

getattr(this_module, 's2')

导入其他模块,利用反射查找该模块是否存在某个方法

def test():

    print('from the test')

"""

程序目录:

    module_test.py

    index.py

当前文件:

    index.py

"""import module_test as obj#obj.test()print(hasattr(obj,'test'))

getattr(obj,'test')()


__str__和__repr__

改变对象的字符串显示__str__,__repr__

自定制格式化字符串__format__

#_*_coding:utf-8_*_format_dict={

    'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型    'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址    'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名}class School:

    def __init__(self,name,addr,type):

        self.name=name

        self.addr=addr

        self.type=type

    def __repr__(self):

        return 'School(%s,%s)' %(self.name,self.addr)

    def __str__(self):

        return '(%s,%s)' %(self.name,self.addr)

    def __format__(self, format_spec):

        # if format_spec        if not format_spec or format_spec not in format_dict:

            format_spec='nat'        fmt=format_dict[format_spec]

        return fmt.format(obj=self)

s1=School('oldboy1','北京','私立')print('from repr: ',repr(s1))print('from str: ',str(s1))print(s1)'''

str函数或者print函数--->obj.__str__()

repr或者交互式解释器--->obj.__repr__()

如果__str__没有被定义,那么就会使用__repr__来代替输出

注意:这俩方法的返回值必须是字符串,否则抛出异常

'''print(format(s1,'nat'))print(format(s1,'tna'))print(format(s1,'tan'))print(format(s1,'asfdasdffd'))

class B:

    def __str__(self):

        return 'str : class B'    def __repr__(self):

        return 'repr : class B'b=B()print('%s'%b)print('%r'%b)


__del__

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

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

class Foo:

    def __del__(self):

        print('执行我啦')

f1=Foo()del f1print('------->')#输出结果执行我啦

------->



item系列

__getitem__\__setitem__\__delitem__

class Foo:

    def __init__(self,name):

        self.name=name

    def __getitem__(self, item):

        print(self.__dict__[item])

    def __setitem__(self, key, value):

        self.__dict__[key]=value

        print("f1['age']=18时,我执行")

    def __delitem__(self, key):

        print('del obj[key]时,我执行')

        self.__dict__.pop(key)

    def __delattr__(self, item):

        print('del obj.key时,我执行')

        self.__dict__.pop(item)

f1=Foo('sb')

# __dict__[item] 内部是以字典的形式保存数据

# __setitem__设置 key, value

f1['age']=18

f1['age1']=19

# __getitem__ 输出设置的值

print(f1.age) 

# __delattr__ 根据Key删除设置的属性

del f1.age1

# __delitem__ 根据value删除设置的属性

del f1['age']

f1['name']='alex'

print(f1.__dict__)

__new__

View Code

class A:

    def __init__(self):

        self.x = 1

        print('in init function')

    def __new__(cls, *args, **kwargs):

        print('in new function')

        return object.__new__(A, *args, **kwargs)

a = A()

print(a.x)

单例模式

class Singleton:

    def __new__(cls, *args, **kw):

        if not hasattr(cls, '_instance'):

            cls._instance = object.__new__(cls, *args, **kw)

        return cls._instance

one = Singleton()

two = Singleton()

two.a = 3print(one.a)# 3

# one和two完全相同,可以用id(), ==, is检测print(id(one))# 29097904print(id(two))# 29097904print(one == two)# Trueprint(one is two)


__call__

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

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

class Foo:

    def __init__(self):

        pass   

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

        print('__call__')

obj = Foo() # 执行 __init__obj()      # 执行 __call__


__len__

class A:

    def __init__(self):

        self.a = 1

        self.b = 2

    def __len__(self):

        return len(self.__dict__)

a = A()print(len(a))


__hash__

class A:

    def __init__(self):

        self.a = 1

        self.b = 2

    def __hash__(self):

        return hash(str(self.a)+str(self.b))

a = A()print(hash(a))


__eq__

class A:

    def __init__(self):

        self.a = 1

        self.b = 2

    def __eq__(self,obj):

        if  self.a == obj.a and self.b == obj.b:

            return True

a = A()

b = A()print(a == b)


纸牌游戏

from collections import namedtuple

Card = namedtuple('Card',['rank','suit'])

class FranchDeck:

    ranks = [str(n) for n in range(2,11)] + list('JQKA')

    suits = ['红心','方板','梅花','黑桃']

    def __init__(self):

        self._cards = [Card(rank,suit) for rank in FranchDeck.ranks

                                        for suit in FranchDeck.suits]

    def __len__(self):

        return len(self._cards)

    def __getitem__(self, item):

        return self._cards[item]

deck = FranchDeck()print(deck[0])from random import choiceprint(choice(deck))print(choice(deck))

纸牌游戏2

from collections import namedtuple

Card = namedtuple('Card',['rank','suit'])

class FranchDeck:

    ranks = [str(n) for n in range(2,11)] + list('JQKA')

    suits = ['红心','方板','梅花','黑桃']

    def __init__(self):

        self._cards = [Card(rank,suit) for rank in FranchDeck.ranks

                                        for suit in FranchDeck.suits]

    def __len__(self):

        return len(self._cards)

    def __getitem__(self, item):

        return self._cards[item]

    def __setitem__(self, key, value):

        self._cards[key] = value

deck = FranchDeck()

print(deck[0])

from random import choice

print(choice(deck))

print(choice(deck))

from random import shuffle

shuffle(deck)

print(deck[:5])

一道面试题

class Person:

    def __init__(self,name,age,sex):

        self.name = name

        self.age = age

        self.sex = sex

    def __hash__(self):

        return hash(self.name+self.sex)

    def __eq__(self, other):

        if self.name == other.name and self.sex == other.sex:return True

p_lst = []for i in range(84):

    p_lst.append(Person('egon',i,'male'))print(p_lst)print(set(p_lst))

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容