Skip to content

Commit d9beaa0

Browse files
committed
learning at 20190929
1 parent 381d7d6 commit d9beaa0

4 files changed

Lines changed: 214 additions & 0 deletions

File tree

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# 这里用两种方式定了palyer类,一种是palyer1,一种是palyer2
2+
3+
4+
class Player1:
5+
def __init__(self, uid, name, level):
6+
self.uid = uid
7+
self.name = name
8+
self.level = level
9+
10+
11+
class Player2:
12+
__slots__ = ['uid', 'name', 'level'] # 类属性
13+
def __init__():
14+
self.uid = uid
15+
self.name = name
16+
self.level = level
17+
18+
19+
p1 = Player1('0001', 'Jim', 20)
20+
p2 = Player2('0001', 'Jim', 20)
21+
dir(p1)
22+
dir(p2)
23+
set(dir(p1)) - set(dir(p2)) # 主要浪费内存的地方是__dict__,其用于动态属性的维护
24+
p1.__dict__['z'] = 300 # 等同于p1.z = 300
25+
26+
import sys
27+
28+
sys.getsizeof(p1.__dict__) # 864 bytes
29+
sys.getsizeof(p1.name) # 52 bytes
30+
sys.getsizeof(p1.level) # 28 bytes
31+
sys.getsizeof(p1.uid) # 53 bytes
32+
33+
# 为了避免内存的浪费,就关闭动态属性
34+
# p2.x = 1 # AttributeError
35+
36+
# 测试
37+
38+
import tracemalloc # 跟踪内存使用
39+
40+
tracemalloc.start()
41+
# start
42+
la = [Player1(1,2,3) for _ in range(100000)]
43+
#lb = [Player2(1,2,3) for _ in range(100000)]
44+
# end
45+
snapshot = tracemalloc.take_snapshot()
46+
#top_stats = snapshot.statistics('lineno')
47+
top_stats = snapshot.statistics('filename')
48+
for stat in top_stats[:10]: print(stat)
49+
50+
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from sys import stdin, stdout
2+
import getpass
3+
import telnetlib
4+
from collections import deque
5+
6+
class TelnetClient:
7+
def __init__(self, host, port=23):
8+
self.host = host
9+
self.port = port
10+
11+
def connect(self):
12+
self.tn = telnetlib.Telnet(self.host, self.port)
13+
self.history = deque([])
14+
15+
def cleanip(self):
16+
self.tn.close()
17+
self.tn = None
18+
19+
with open('history.txt', 'a') as f:
20+
f.writelienes(self.history)
21+
22+
def login(self):
23+
# user
24+
self.tn.read_until(b"login: ")
25+
user = input("Enter your remote account: ")
26+
self.tn.write(user.encode('utf8') + b'\n')
27+
28+
# password
29+
self.tn.read_until(b'Password: ')
30+
password = getpass.getpass()
31+
self.tn.write(password.encode('utf8') + b'\n')
32+
out = self.tn.read_until(b'$ ')
33+
stdout.write(out.decode('utf8'))
34+
35+
def interact(self):
36+
while True:
37+
cmd = stdin.readline()
38+
if not cmd:
39+
break
40+
41+
self.history.append(cmd)
42+
self.tn.write(cmd.encode('utf8'))
43+
out = self.tn.read_until(b'$ ').decode('utf8')
44+
45+
stdout.write(out[len(cmd)+1:])
46+
stdout.flush()
47+
48+
49+
client = TelnetClient('192.168.0.105')
50+
client.connect()
51+
client.login()
52+
client.interact()
53+
client.cleanup()
54+
55+
# with上下文管理说明
56+
#with open('demo.txt', 'w') as f:
57+
# f.write('abc')
58+
# f.write('efef')
59+
#
60+
#f.close # 返回True
61+
#
62+
#F = open('demo.txt', 'w')
63+
#f = F.__enter__() # with上下文管理需要的方法,只不过此方法实现中返回的是F. 进入的时候调用此方法
64+
#f is F # 返回True
65+
#F.__exit__() # 退出的时候调用此方法
66+
67+
# 所以需要将上面代码中的connect , cleanup方法分别改成__enter__和__exit__方法
68+
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from sys import stdin, stdout
2+
import getpass
3+
import telnetlib
4+
from collections import deque
5+
6+
class TelnetClient:
7+
def __init__(self, host, port=23):
8+
self.host = host
9+
self.port = port
10+
11+
# def connect(self):
12+
# self.tn = telnetlib.Telnet(self.host, self.port)
13+
# self.history = deque([])
14+
def __enter__(self):
15+
self.tn = telnetlib.Telnet(self.host, self.port)
16+
self.history = deque([])
17+
18+
# def cleanup(self):
19+
# self.tn.close()
20+
# self.tn = None
21+
#
22+
# with open('history.txt', 'a') as f:
23+
# f.writelienes(self.history)
24+
def __exit_(self, exc_type, exc_value, exc_tb):
25+
self.tn.close()
26+
self.tn = None
27+
28+
with open('history.txt', 'a') as f:
29+
f.writelienes(self.history)
30+
31+
def login(self):
32+
# user
33+
self.tn.read_until(b"login: ")
34+
user = input("Enter your remote account: ")
35+
self.tn.write(user.encode('utf8') + b'\n')
36+
37+
# password
38+
self.tn.read_until(b'Password: ')
39+
password = getpass.getpass()
40+
self.tn.write(password.encode('utf8') + b'\n')
41+
out = self.tn.read_until(b'$ ')
42+
stdout.write(out.decode('utf8'))
43+
44+
def interact(self):
45+
while True:
46+
cmd = stdin.readline()
47+
if not cmd:
48+
break
49+
50+
self.history.append(cmd)
51+
self.tn.write(cmd.encode('utf8'))
52+
out = self.tn.read_until(b'$ ').decode('utf8')
53+
54+
stdout.write(out[len(cmd)+1:])
55+
stdout.flush()
56+
57+
58+
#client = TelnetClient('192.168.0.105')
59+
#client.connect()
60+
#client.login()
61+
#client.interact()
62+
#client.cleanup()
63+
64+
with TelnetClient('192.168.0.105') as client:
65+
client.login()
66+
client.interact()
67+
68+
print('END')

python3_programming_tricks/ch07/7_class_and_object.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,31 @@ IntTuple([1, -1, 'abc', 6, ['x','y'],3]) => (1,6,3)
1515
**解决方案**
1616

1717
继承内置tuple,并实现\_\_new\_\_.在其中修改实例化行为
18+
19+
## 7.2 如何为创建大量实例节省内存
20+
21+
**实际案例**
22+
23+
在某网络游戏中,定义了玩家类Player(id, name, level, ...).每有一个在线玩家,在服务器程序内则有一个Player实例。
24+
当在线人数很多时,将产生大量实例。(如百万级)
25+
如何降低这些大量实例的内存开销?
26+
27+
**解决方案**
28+
29+
定义类的\_\_slots\_\_属性,声明实例有哪些属性(关闭动态绑定)
30+
31+
## 7.3 如何让对象支持上下文管理
32+
33+
**实际案例**
34+
35+
我们实现了一个telnet客户端的类TelnetClient,调用实例的connect(),login(),interact()方法启动客户端与服务器交互,交互完毕后需要调用cleanup()方法,关闭已连接的socket,以及操作历史记录写入文件并关闭。
36+
能否让TelnetClient的实例支持上下文管理协议,从而替代手工调用cennect(), cleanup()方法。
37+
38+
**解决方案**
39+
40+
实现上下文管理协议,即实现类的\_\_enter\_\_,\_\_exit\_\_方法
41+
它们分别在with开始和结束时被调用
42+
43+
44+
45+

0 commit comments

Comments
 (0)