Python双下划线方法和单列模式

isinstance(obj, cls)方法判断obj是否是cls的对象

class Foo(object):
    pass

obj = Foo()
print(isinstance(obj, Foo))   # True

issubclass(sub, super)判断sub类是否是super类的派生类或子类

class Foo(object):
    pass

class Bar(Foo):
    pass

print(issubclass(Bar, (Foo,)))     # True

可以调用类的私有属性

class Foo(object):
    def __init__(self,name,age):
        self.name = name
        self.__age = age     # 私有方法

    def func(self):
        print(self.__age)    # 在当前类中可调用


obj = Foo('xiaohei', 50)
print(obj.name)
print(obj.__age)         # 拒绝常规方法的调用
print(obj._Foo__age)     # 强制调用类的私有方法
obj.func()
View Code

Python中设计模式的单列模式

class Singleton(object):
    """
    Python中设计模式的单列模式
    """
    # 设置类的私有属性即标志位
    __instance = False

    def __init__(self, name, age):
        # self是经过cls转化而来
        self.name = name
        self.age = age

    def __new__(cls, *args, **kwargs):
        """
        在这里控制对象的创建方式,在内存层面始终指向同一个内存地址即同一对象
        :param cls: 代指当前类
        :param __new__: 构造方法
        :param args:
        :param kwargs:
        """
        if cls.__instance:
            # 再次运行时之前已经生成自己的类,则使用自己的
            return cls.__instance
        Singleton.__instance = object.__new__(cls)
        # 借助object.__new__构造方法,第一次运行时创建一个新对象cls(当前类)
        return Singleton.__instance


# 实例化两个对象
alex = Singleton("Alex", 29)
# 多设置一个属性
alex.sex = ""
jim = Singleton("Jim", 25)
# <__main__.Singleton object at 0x000001F24903BB70>   一样的内存地址
# <__main__.Singleton object at 0x000001F24903BB70>
print(alex)
print(jim)
print(alex.name)        # Jim
print(jim.name)         # Jim 因为是一样的地址,所以同属性会被覆盖
print(alex.sex)         # 男  后面生成的对象没有这个属性,不会被覆盖
print(jim.sex)          # 男  因为是一样的地址,所以其他对象有的属性也可以调用

自己使用双下划线方法制作扑克牌

import json
from collections import namedtuple
# 调用namedtuple()生成Card类
Card = namedtuple("Card", ["rank", "suit"])      # rank 牌面大小   suit 牌面花色


class FranchDeck:
    ranks = [str(i) for i in range(2, 11)] + list("JQKA")     # 设置牌面总数
    suits = ["黑桃", "红心", "梅花", "方块"]                   # 设置花色总数

    def __init__(self):
        # 两层for循环生成一副牌
        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

    def __str__(self):
        return json.dumps(self._cards, ensure_ascii=False)


deck = FranchDeck()
# 调用__getitem__()方法取值
print(deck[9])
# 调用父类object的__getattr__()方法获取花色
print(deck[9].suit)
from random import choice
# choice()方法需要知道牌面总数也是__len__()方法
print(choice(deck))
from random import shuffle
# shuffle()方法打乱列表顺序需要__setitem__()方法
shuffle(deck)
print(deck[9])
print(deck)     # 打印字符串的友好方式需要__str__()方法

使用set()去重对象

"""
使用set()去重对象
"""
import json

class People(object):

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

    def __eq__(self, other):
        # __eq__ 定义了类的等号(==)行为
        if self.name == other.name and self.sex == other.sex:
            return True
        return False

    def __hash__(self):
        return hash(self.name + self.sex)


# 生成两个对象
alex = People("Alex", "", 35)
alex_one = People("Alex", "", 29)
# 存储在不同内存地址<__main__.People object at 0x000002972250BB70> <__main__.People object at 0x000002972250BD30>
print(alex, alex_one)
# 使用set()去重之后{<__main__.People object at 0x00000120B6E6BB70>}
# set()对对象操作就需要调用对象的内置方法
print(set((alex, alex_one)))    # set()依赖的对象方法是 __eq__和__hash__
alex_two = set((alex, alex_one))
# 遍历取值会发现取用的还是第一个对象的属性
for item in alex_two:
    print(item.age)     # 35

反射(通过字符串的形式操作对象的相关属性)

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('Peppa', 15)

#检测是否含有某属性
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', "Pig")
setattr(obj,'show_name',lambda self:self.name+'sb')
print(obj.__dict__)
print(obj.show_name(obj))

#删除属性
delattr(obj,'age')
delattr(obj,'show_name')

print(obj.__dict__)
原文地址:https://www.cnblogs.com/Guishuzhe/p/9780610.html