2019独角兽企业重金招聘Python工程师标准>>>

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

问题1: 我们想定义一种新类型的元组,对于传入的可迭代对象,我们只保留其中int类型且值大于0的元素,例如:IntTuple([1,-1,'abc',6,['x','y'],3])==>(1,6,3),要求IntTuple是内置tuple的子类,如何实现?

解决方案:定义类IntTuple继承tuple,并实现__new__,修改实例化行为

__new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而 __new__方法正是创建这个类实例的方法。new方法会返回所构造的对象,init则不会,在使用new返回对象的时候会隐式调用init函数。new函数必须以cls作为第一个参数,而init则以self作为其第一个参数

class IntTuple(tuple):def __new__(cls, iterable):g = (x for x in iterable if isinstance(x,int) and x > 0)return super(IntTuple, cls).__new__(cls,g)def __init__(self, iterable):return super(IntTuple,self).__init__(iterable)t = IntTuple([1,-1,'abc',6,['x','y'],3])
print t输出:
(1, 6, 3)

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

问题2: 某网络游戏中,定义了玩家类Player(id,name,status,...),每有一个在线玩家,服务器内部则有一个Player的实例,当在线人数很多时,将产生大量实例,如何降低这些大量实例的内存开销

解决方案:定义类的__slots__属性,它是用来声明实例属性名字的列表

class Player(object):def __init__(self,uid,name,status=0,level=1):self.uid = uidself.name = nameself.status = statusself.level = levelclass Player2(object):__slots__ = ['uid', 'name', 'status', 'level']def __init__(self,uid,name,status=0,level=1):self.uid = uidself.name = nameself.status = statusself.level = levelp1 = Player('0001',"Jim")
p2 = Player2('0001',"jim")print dir(p1)
print '\n'
print dir(p2)
print '\n'
print set(dir(p1)) -set(dir(p2))输出:['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'level', 'name', 'status', 'uid']['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'level', 'name', 'status', 'uid']set(['__dict__', '__weakref__'])# 可以看到使用__slots__属性的类,比正常的少了__dict__,即不可以动态绑定属性,但是也减少了内存消耗,因为__dict__使用会占用内存

3.如何让对象支持上下文管理

问题3: 实现了一个telnet客户端的类TelnetClient,调用实例的start()方法启动客户端与服务器交互,交互完毕后需要调用cleanup方法关闭已连接的socket,以及将操作历史记录写入文件并关闭,能否让TelnetClient的实例支持上下文管理协议,从而替代手工调用cleanup()方法

from telnetlib import Telnet
from sys import stdin, stdout
from collections import dequeclass TelnetClient(object):def __init__(self, addr, port=23):self.addr = addrself.port = portself.tn = Nonedef start(self):self.tn = Telnet(self.addr, self.port)self.history = deque()# usert = self.tn.read_until('login: ')stdout.write(t)user = stdin.readline()self.tn.write(user)# passwordt = self.tn.read_until('Password: ')if t.startswith(user[::-1]):t = t[len(user) + 1:]stdout.write(t)self.tn.write(stdin.readline())t = self.tn.read_until('$ ')stdout.write(t)while True:uinput = stdin.readline()if not uinput:breakself.history.append(uinput)self.tn.write(uinput)t = self.tn.read_until('$ ')stdout.write(t[len(user) + 1:])def cleanup(self):self.tn.close()self.tn = Nonewith open(self.addr + '_history.txt', 'w') as f:f.writelines(self.history)client = TelnetClient('127.0.0.1')
print '\nstart'
client.start()
print '\ncleanup'
client.cleanup()

执行Python文件,输入用户名,密码登录telnet服务器,然后输入命令进行测试,然后ctrl + D退出,发现此时会生成127.0.0.1_history.txt文件,里面记录了操作的历史命令

解决方案:

实现上下文管理协议,需定义实例的__enter__,__exit__方法,它们分别在with开始和结束时被调用

from telnetlib import Telnet
from sys import stdin, stdout
from collections import dequeclass TelnetClient(object):def __init__(self, addr, port=23):self.addr = addrself.port = portself.tn = Nonedef start(self):# usert = self.tn.read_until('login: ')stdout.write(t)user = stdin.readline()self.tn.write(user)# passwordt = self.tn.read_until('Password: ')if t.startswith(user[::-1]):t = t[len(user) + 1:]stdout.write(t)self.tn.write(stdin.readline())t = self.tn.read_until('$ ')stdout.write(t)while True:uinput = stdin.readline()if not uinput:breakself.history.append(uinput)self.tn.write(uinput)t = self.tn.read_until('$ ')stdout.write(t[len(user) + 1:])def __enter__(self):self.tn = Telnet(self.addr, self.port)self.history = deque()return selfdef __exit__(self, exc_type, exc_val, exc_tb):self.tn.close()self.tn = Nonewith open(self.addr + '_history.txt', 'w') as f:f.writelines(self.history)# with TelnetClient('127.0.0.1') as client的对象是 __enter__方法return返回的对象,当start()方法抛出异常时,仍然会执行__exit__里面的方法
with TelnetClient('127.0.0.1') as client:client.start()

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

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

解决方案: 使用内置的property函数,Python内置的@property装饰器就是负责把一个方法变成属性调用

from math import piclass Circle(object):def __init__(self, radius):self.radius = radiusdef getRadius(self):return self.radiusdef setRadius(self, value):if not isinstance(value, (int, long, float)):raise ValueError('wrong type')self.radius = float(value)def getArea(self):return self.radius ** 2 * piR = property(getRadius, setRadius)c = Circle(3.2)
# 得到getRadius方法里的值
print c.R
# 使用setRadius设置值
c.R = 5.9
print c.R输出:
3.2
5.9

5.如何让类支持比较操作

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

解决方案:比较符号运算符重载,需要实现以下方法__lt__和__le__和__gt__和__eq__和__ne__

使用标准库下的functools下的类装饰器total_ording 可以简化此过程

使用total_ordering装饰器的时候,类里面需要定义__eq__和大于__gt__或小于__lt__的一个方法

from functools import total_ordering@total_ordering
class Rectangle(object):def __init__(self, w, h):self.w = wself.h = hdef area(self):return self.w * self.hdef __lt__(self, obj):return self.area() < obj.area()def __eq__(self, obj):return self.area() == obj.area()r1 = Rectangle(5, 3)
r2 = Rectangle(4, 4)
print r1 < r2输出:
True

两个类的实例化进行比较,两个类里要有共同的方法area,都是比较面积

from functools import total_ordering@total_ordering
class Rectangle(object):def __init__(self, w, h):self.w = wself.h = hdef area(self):return self.w * self.hdef __lt__(self, obj):return self.area() < obj.area()def __eq__(self, obj):return self.area() == obj.area()class Circle(object):def __init__(self, r):self.r = rdef area(self):return self.r ** 2 * 3.14r1 = Rectangle(5, 3)
r2 = Rectangle(4, 4)
c1 = Circle(3)
print r1 < c1输出:
True

使用抽象基类的方式来进行比较两个类

from functools import total_ordering
from abc import ABCMeta, abstractmethod@total_ordering
class Shape(object):@abstractmethoddef area(self):passdef __lt__(self, obj):if not isinstance(obj, Shape):raise TypeError('obj is not shape')return self.area() < obj.area()def __eq__(self, obj):return self.area() == obj.area()class Rectangle(Shape):def __init__(self, w, h):self.w = wself.h = hdef area(self):return self.w * self.hclass Circle(Shape):def __init__(self, r):self.r = rdef area(self):return self.r ** 2 * 3.14r1 = Rectangle(5, 3)
r2 = Rectangle(4, 4)
c1 = Circle(3)
print c1 >= r1输出:
True

6.如何使用描述符对实例属性做类型检查

问题6: 在某项目中我们实现了一些类,并希望能像静态类型语言那样(C,C++,Java)对它们的实例属性做类型检查

p = Person()
p.name = 'bob' # 必须是str
p.age = 18     # 必须是int
p.height = 1.83 # 必须是float

要求: 可以对实例变量名指定类型,赋予不正确类型时抛出异常

解决方案:使用描述符来实现需要类型检查的属性,分别实现__get__和__set__和__delete__方法,在__set__内使用isinstance函数做类型检查


class Attr(object):def __init__(self, name, type_):self.name = nameself.type_ = type_def __get__(self, instance, cls):return instance.__dict__[self.name]def __set__(self, instance, value):if not isinstance(value, self.type_):raise TypeError('expected an %s' % self.type_)instance.__dict__[self.name] = valuedef __delete__(self, instance):del instance.__dict__[self.name]class Person(object):name = Attr('name', str)age = Attr('age', int)height = Attr('height', float)p = Person()
p.name = 'Bob'
print p.name
# 由于age定义的类型是int,故传递str会报错
p.age = '18'输出:Bob
Traceback (most recent call last):File "/home/yangyang/train/shuxing.py", line 28, in <module>p.age = '18'File "/home/yangyang/train/shuxing.py", line 13, in __set__raise TypeError('expected an %s' % self.type_)
TypeError: expected an <type 'int'>

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

问题7: 在python中,垃圾回收器通过引用计数来回收垃圾对象,但某些环状结构存在对象间的循环引用,比如树的父节点引用子节点,子节点也同时引用父节点.此时同时del掉引用父子节点,两个对象不能被立即回收.如何解决此类的内存管理问题?

解决方案: 使用标准库weakref,它可以创建一种能访问对象但不增加引用计数的对象

引用计数例子:

In [1]: class A(object):...:     def __del__(self):...:         print 'in A.__del__'...:         In [2]: a = A()In [3]: import sys
# 查看A()的引用计数,用sys.getrefcount()函数,比期望值多1
In [4]: sys.getrefcount(a)
Out[4]: 2In [5]: a = 5
in A.__del__

循环引用例子:

class Data(object):def __init__(self, owner, value):# 这里引用了Node,因为Node引用的时候传入了自身self.owner = ownerself.value = valuedef __str__(self):return "%s's data, value is %s" % (self.owner, self.value)def __del__(self):print "in Data.__del__"class Node(object):def __init__(self, value):# 这里引用了Dataself.data = Data(value, self)def __del__(self):print "in Node.__del__"node = Node(100)
del node
raw_input("wait....")输出:
wait

解决循环引用例子

import weakrefclass Data(object):def __init__(self, value, owner):self.value = valueself.owner = weakref.ref(owner)def __str__(self):return "%s's data, value is %s" % (self.owner(), self.value)def __del__(self):print "in Data.__del__"class Node(object):def __init__(self, value):self.data = Data(value, self)def __del__(self):print "in Node.__del__"node = Node(100)
del node
raw_input("wait....")输出:in Node.__del__
in Data.__del__
wait....

8.如何通过实例方法名字的字符串调用方法

问题8:某项目中,我们的代码使用了三个不同库中的图形类,Circle, Triangle,Rectangle,它们都有一个获取图形面积的方法,但方法名字不同,我们可以实现一个统一的获取面积的函数,使用每种方法名进行尝试,调用相应类的接口

解决方案:

方法一:使用内置函数getattr,通过名字在实例上获取方法对象,然后调用

方法二:使用标准库下operator下的methodcaller函数调用

# test.pyfrom lib1 import Circle
from lib2 import Triangle
from lib3 import Rectangledef getArea(shape):for name in ('area', 'getArea', 'get_area'):f = getattr(shape, name, None)if f:return f()shape1 = Circle(2)
shape2 = Triangle(3, 4, 5)
shape3 = Rectangle(6, 4)shapes = [shape1, shape2, shape3]print map(getArea, shapes)输出:
[12.56, 6.0, 24]
#lib1.pyclass Circle(object):def __init__(self, r):self.r = rdef area(self):return self.r ** 2 * 3.14
# lib2.pyclass Triangle(object):def __init__(self, a, b, c):self.a = aself.b = bself.c =cdef getArea(self):a, b, c = self.a, self.b, self.cp = (a + b + c)/2area = (p * (p - a) * (p - b) * (p - c)) ** 0.5return area
# lib3.pyclass Rectangle(object):def __init__(self, w, h):self.w = wself.h = hdef get_area(self):return self.w * self.h

转载于:https://my.oschina.net/zhangyangyang/blog/901850

Python类与对象相关推荐

  1. python类包含对象的个数_python类与对象各个算数运算魔法方法总结

    1.python类与对象各个算术运算魔法方法总结: 2.各个魔法方法应用举例: 3.实例训练: (1)我们都知道在 Python 中,两个字符串相加会自动拼接字符串,但遗憾的是两个字符串相减却抛出异常 ...

  2. Python类与对象实验

    一.任务描述   本实验任务主要对Python类与对象进行一些基本操作,通过完成本实验任务,要求学生熟练掌握Python类与对象的关系,并对Python类与对象的基本操作进行整理并填写工作任务报告. ...

  3. 【Python基础入门系列】第10天:Python 类与对象

    首先,我已经假定你是个萌新或已经看了无数遍的垃圾文章,然后依然搞不懂类和对象,但是呢起码知道有类和对象这么两个玩意儿,我觉得有必要找一篇生动形象的示例来讲解. 由于你可能没有编程经验, 所以无法从学过 ...

  4. 一文讲全了Python 类和对象内容

    摘要:这是一个关于 Python 类和对象的全部内容. 本文分享自华为云社区<从零开始学python | Python 类和对象-面向对象编程>,原文作者:Yuchuan  . Pytho ...

  5. python类和对象_Python类和对象

    python类和对象 Python is an object-oriented programming language. Python Classes and Objects are the cor ...

  6. python中对象的特性_python中类与对象之继承,python类和对象理解,面对对象的三大特性之...

    python中类与对象之继承,python类和对象理解,面对对象的三大特性之 面对对象的三大特性之继承 1.什么是继承? 在程序中,继承指的是class与class之间的关系 继承是一种关系,必须存在 ...

  7. python类、对象、方法、属性之类与对象笔记

    为什么80%的码农都做不了架构师?>>>    python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,坐着的椅子就是对象,家里养的小狗也是一个对象...... ...

  8. python——类和对象之__dict__属性的使用

    在 Python 类的内部,无论是类属性还是实例属性,都是以字典的形式进行存储的,其中属性名作为键,属性值作为对应的值. __dict__,可以使用类名或者类的实例对象来调用, 用类名直接调用__di ...

  9. python类和对象介绍_python中的类,对象,方法,属性等介绍

    注:这篇文章写得很好.加底纹的是我自己的理解 python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,坐着的椅子就是对象,家里养的小狗也是一个对象...... 我们通过描述属性( ...

  10. python类和对象详解_Python公开课 - 详解面向对象

    前言 在C语言中,单纯通过结构化的函数也可以实现很好的软件,顺序思路比较好理解:而C++则以面向对象的思维来进行代码组织,通过定义对象.成员变量.成员函数.以封装.继承和多态等方式来更灵活处理业务逻辑 ...

最新文章

  1. python 怎么将数组转为列表_图片转换成pdf格式怎么操作?什么软件能将图片转为pdf?...
  2. 伪静态技术(SEO) 摘自:http://bbs.admin5.com/thread-8522290-1-1.html
  3. Patent Writing and cultivation of innovation thinking
  4. 3.QT中QCommandLineParser和QCommandLineOption解析命令行参数
  5. Golang中GOPATH在Goland的理解
  6. 非Java专家的APM:什么泄漏?
  7. 使用dwebsocket在Django中使用Websocket
  8. winform 填充圆形 锯齿_Qt项目中,三种图形渐变填充方式详细总结
  9. 3d激光雷达开发(八叉树)
  10. @RestControllerAdvice与@ControllerAdvice的区别
  11. mysql 命令行执行存储过程_mysql 命令行执行存储过程
  12. linux 程序发包,软件测试常用linux发包命令
  13. Android直播APP源码搭建中豪华物特效的实现
  14. 【感悟】参加公司首届黑客马拉松有感
  15. 【CCF】小中大(C++)
  16. 日常英语口语900句
  17. C++实现走迷宫算法(1)
  18. 获取apk运行占手机RAM大小
  19. 傲盾linux防火墙,linux 挂载数据盘指引
  20. CPU的主频/核心数

热门文章

  1. linux 下 ifcfg-eth0 配置
  2. [零基础学JAVA]Java SE应用部分-27.Java IO操作(01)
  3. linux挂载其他硬盘
  4. golang适合做什么_这年头中年女人适合做什么兼职
  5. Python要了解哪些编程基础 如何学Python比较好
  6. python3 namedtuple_你不能低估的Python数据结构Namedtuple(二)
  7. c++程序影像读取_应急响应手册程序执行痕迹
  8. Linux工业嵌入式应用
  9. C++ 枚举类型介绍
  10. Splay ---- 区间翻转 区间最大值 区间加 P4146 序列终结者