面向对象双下划线方法

Posted huanghongzheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象双下划线方法相关的知识,希望对你有一定的参考价值。

1|0阅读目录


2|0isinstance和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)
技术图片
技术图片

 

3|0反射


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
技术图片
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
技术图片
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
技术图片
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 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)
print getattr(Foo, bar)
类也是对象

 

技术图片
#!/usr/bin/env python
# -*- 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)
反射当前模块成员

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

技术图片 View Code
技术图片
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
"""
程序目录:
    module_test.py
    index.py
 
当前文件:
    index.py
"""

import module_test as obj

#obj.test()

print(hasattr(obj,test))

getattr(obj,test)()
View Code

 

4|0__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))
View Code
技术图片
class B:

     def __str__(self):
         return str : class B

     def __repr__(self):
         return repr : class B


b=B()
print(%s%b)
print(%r%b)
%s和%r

 

 

5|0item系列


__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
    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)
f1[age]=18
f1[age1]=19
del f1.age1
del f1[age]
f1[name]=alex
print(f1.__dict__)
View Code

6|0__del__


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

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

技术图片
class Foo:

    def __del__(self):
        print(执行我啦)

f1=Foo()
del f1
print(------->)

#输出结果
执行我啦
------->
简单示范

 

7|0__new__


技术图片
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)

a = A()
print(a.x)
View Code
技术图片
class Singleton:
    def __new__(cls, *args, **kw):
        if not hasattr(cls, _instance):
            cls._instance = object.__new__(cls)
        return cls._instance

one = Singleton()
two = Singleton()

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

单例模式
单例模式

 

8|0__call__


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

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

技术图片
class Foo:

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

        print(__call__)


obj = Foo() # 执行 __init__
obj()       # 执行 __call__
View Code

 

9|0with和__enter__,__exit__


技术图片
class A:
    def __enter__(self):
        print(before)

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(after)


with A() as a:
    print(123)
with语句
技术图片
class A:
    def __init__(self):
        print(init)
        
    def __enter__(self):
        print(before)

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(after)


with A() as a:
    print(123)
with语句和init
技术图片
class Myfile:
    def __init__(self,path,mode=r,encoding = utf-8):
        self.path = path
        self.mode = mode
        self.encoding = encoding

    def __enter__(self):
        self.f = open(self.path, mode=self.mode, encoding=self.encoding)
        return self.f

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()


with Myfile(file,mode=w) as f:
    f.write(wahaha)
with和文件操作
技术图片
import  pickle
class MyPickledump:
    def __init__(self,path):
        self.path = path

    def __enter__(self):
        self.f = open(self.path, mode=ab)
        return self

    def dump(self,content):
        pickle.dump(content,self.f)

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()

class Mypickleload:
    def __init__(self,path):
        self.path = path

    def __enter__(self):
        self.f = open(self.path, mode=rb)
        return self


    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()

    def load(self):
         return pickle.load(self.f)


    def loaditer(self):
        while True:
            try:
                yield  self.load()
            except EOFError:
                break



# with MyPickledump(file) as f:
#      f.dump(1,2,3,4)

with Mypickleload(file) as f:
    for item in f.loaditer():
        print(item)
with和pickle
技术图片
import  pickle
class MyPickledump:
    def __init__(self,path):
        self.path = path

    def __enter__(self):
        self.f = open(self.path, mode=ab)
        return self

    def dump(self,content):
        pickle.dump(content,self.f)

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()

class Mypickleload:
    def __init__(self,path):
        self.path = path

    def __enter__(self):
        self.f = open(self.path, mode=rb)
        return self


    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()

    def __iter__(self):
        while True:
            try:
                yield  pickle.load(self.f)
            except EOFError:
                break



# with MyPickledump(file) as f:
#      f.dump(1,2,3,4)

with Mypickleload(file) as f:
    for item in f:
        print(item)
with和pickle和iter

 

 

10|0__len__


技术图片
class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __len__(self):
        return len(self.__dict__)
a = A()
print(len(a))
View Code

 

11|0__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))
View Code

 

12|0__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)
View Code

 

技术图片
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 choice
print(choice(deck))
print(choice(deck))
纸牌游戏
技术图片
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])
纸牌游戏2
技术图片
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))
一道面试题

 

以上是关于面向对象双下划线方法的主要内容,如果未能解决你的问题,请参考以下文章

面向对象 | 双下方法

Python面向对象中的“私有化”

Python面向对象基础知识

面向对象——封装

python面向对象面试集锦(1-23)

Python全栈之路----面向对象开发----封装