563 views
Python高级技巧

2.类与对象深度问题与解决技巧

文章目录

类与对象深度问题与解决技巧

如何派生内置不可变类型并修改其实例化行为

我们想自定义一种新类型的元组,对于传入的可迭代对象,我们只保留其中int类型且值大于0的元素,例如:

IntTuple([2,-2,"jr",["x","y"],4]) =》 (2,4)

如何继承内置tuple 实现IntTuple

如何为创建大量实例节省内存

在游戏中,定义了玩家类player,每有一个在线玩家,在服务器内则有一个player的实例,当在线人数很多时,将产生大量实例(百万级)
问题:
1.如何降低这些大量实例的内存开销?
2.解决方案:

  • 定义类的__slots__属性,声明实例有哪些属性(关闭__dict__动态绑定)
import sys
import tracemalloc


class Player1(object):
    def __init__(self, uid, name, status=0, level=1):
        self.uid = uid
        self.name = name
        self.status = status
        self.level = level


class Player2(object):
    __slots__ = ('uid', 'name', 'status', 'level') #声明关闭动态绑定的变量

    def __init__(self, uid, name, status=0, level=1):
        self.uid = uid
        self.name = name
        self.status = status
        self.level = level


tracemalloc.start()
p1 = [Player1(1, 2, 3) for _ in range(100000)]      # 这里会消耗16.8 MiB
# p2 = [Player2(1, 2, 3) for _ in range(100000)]    # 用了__slots__这里只消耗7837 KiB
end = tracemalloc.take_snapshot()
# top = end.statistics('lineno')
top = end.statistics('filename')

for stat in top[:10]:
    print(stat)       

Python中的with语句

import contextlib
#contextlib简化上下文管理器
@contextlib.contextmanager
def file_open(filename):
    print('file open')
    yield {}
    print('file end'"')

with file_open('lib1.py') as f:
    print('file operation')

如何创建可管理的对象属性

在面向对象编程中,我们把方法看做对象的接口。直接访问对象的属性可能是不安全的,或设计上不够灵活,但是使用调用方法在形式上不如访问属性简洁。

class A:
    def __init__(self, age):
        self.age = age
    def get_age(self):
        return self.age
    def set_age(self, age):
        if not isinstance(age, int):
            raise TypeError('Type Error')
        self.age = age
    # property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
    R = property(get_age, set_age)

    @property       # get
    def S(self):
        return self.age

    @S.setter       # set
    def S(self, age):
        if not isinstance(age, int):
            raise TypeError('Type Error')
        self.age = age


a = A(18)

# 文件读取的  str
# a.age = '20'
# print(type(a.age))
# a.set_age('20')
# print(a.get_age())
# a.R = 20
# print(a.R)

print(a.S)
a.S = 22

如何让类支持比较操作

有时我们希望自定义类的实例间可以使用,<,<=,>,>=,==,!=符号进行比较,我们自定义比较的行业,例如,有一个矩形的类,比较两个矩形的实例时,比较的是他们的面积

如何在环状数据结构中管理内存

双向循环链表

class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

    def add_right(self, node):
        self.right = node
        node.left = self

    def __str__(self):
        return "Node<%s>" % self.data

    def __del__(self):
        print("in __del__: delete %s" % self)

def create_linklist(n):
    head = current = Node(1)
    for i in range(2, n + 1):
        node = Node(i)
        current.add_right(node)
        current = node
    return head

head = create_linklist(1000)
head = None

import time
for _ in range(1000):
    time.sleep(1)
    print("run...")
input("wait...")

通过实例方法名字的字符串调用方法

我们有三个图形类

Circle,Triangle,Rectangle

他们都有一个获取图形面积的方法,但是方法名字不同,我们可以实现一个统一的获取面积的函数,使用每种方法名进行尝试,调用相应类的接口

class Triangle:
    def __init__(self,a,b,c):
        self.a,self.b,self.c = a,b,c

    def get_area(self):
        a,b,c = self.a,self.b,self.c
        p = (a+b+c)/2
        return (p * (p-a)*(p-b)*(p-c)) ** 0.5

class Rectangle:
    def __init__(self,a,b):
        self.a,self.b = a,b

    def getArea(self):
        return self.a * self.b

class Circle:
    def __init__(self,r):
        self.r = r

    def area(self):
        return self.r ** 2 * 3.14159
影子专属博客 赣ICP备17013143号