当前位置:首页 » 编程语言 » pythonweakref

pythonweakref

发布时间: 2022-11-15 13:38:23

Ⅰ 关于python的问题

在python中,左右都加上下划线的变量是属于内建的属性或方法.如__name__、__file__、__doc__、__str__等等

有一个最常用的就是
if __name__ == '__main__':
#do something
用来判断当单独运行这个文件的时候做一些操作

比如我建立一个a类,用dir方法可以看到很多双下划线的属性或方法,比如__doc__返回的就是文档内容,其他的一些可以去查看python文档。

>>> class a(object):
... "This will be displayed in '__doc__'"
... pass
...
>>> b = a()
>>> dir(b)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__mole__', '__new__', '__rece__', '__rece_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
>>> b.__doc__
"This will be displayed in '__doc__'"
>>> type(b.__doc__)
<type 'str'>

Ⅱ Python 实现slots的继承

__slots__ 是python的一大神器。

它有两大的特点:

python文档中这样介绍它

首先第一点,python的动态性一部分源自于 __dict__ ,属性都保存在 __dict__ 的一个字典中,我们可以随时向这个字典添加新内容,这是 MonkeyPatch 的能力。
而当我们显示的声明了 __slots__ ,python将不会给这个类创建 __dict__ 和 __weakref__

没有了 __dict__ 我们便不能随意创建实例属性,而必须遵守 __slots__ 的约定。

对于性能而言,使用了 __slots__ 后,属性会直接存储到对象中,而不是 __dict__ 中,相当于少了一次检索步骤。

__slots__ 的两大优点,对于python来说,是难以拒绝的诱惑。既能限制不必要的动态性,又能提高性能!
但是 __slots__ 遇到继承时,就会出现很多问题。准确的说, __slots__ 不会被继承。当我们用一个不带有 __slots__ 的子类,继承带有 __slots__ 的父类时。子类还是会生成 __dict__ 和 __weakref__ 。

这是之前写的一个metaclass,创建新的类对象时,会进行以下逻辑。

实际上我们的目的正是解决,父类规定的 __slots__ 约束不了无 __slots__ 子类的问题。这个结果令人非常满意

注意这里子类的d,在 pycharm 等IDE中不会提示错误,因为 pycharm 无法探知你的metaclass做了这样 逆天改命 的逻辑。

需要注意一点, __slots__ 是 类对实例属性的约束 ,而类对象无法通过该属性,约束自己。即为类对象添加新属性,仍然是被允许的。

按照正常思路,也许我们应该到metaclass写一个 __slots__ ,但实际上这是不被允许的。
抽空找时间我会考虑下有无可行性。

Ⅲ python 什么时候使用 weakref

和许多其它的高级语言一样,Python使用了垃圾回收器来自动销毁那些不再使用的对象。每个对象都有一个引用计数,当这个引用计数为0时Python能够安全地销毁这个对象。
使用weakref模块,你可以创建到对象的弱引用,Python在对象的引用计数为0或只存在对象的弱引用时将回收这个对象。
一、 创建弱引用
你可以通过调用weakref模块的ref(obj[,callback])来创建一个弱引用,obj是你想弱引用的对象,callback是一个可选的函数,当因没有引用导致Python要销毁这个对象时调用。回调函数callback要求单个参数(弱引用的对象)。
一旦你有了一个对象的弱引用,你就能通过调用弱引用来获取被弱引用的对象。下面的例子创建了一个对socket对象的弱引用:
>>> from socket import *
>>> import weakref
>>> s=socket(AF_INET,SOCK_STREAM)
>>> ref=weakref.ref(s)
>>> s
<socket._socketobject instance at 007B4A94>
>>> ref
<weakref at 0x81195c; to 'instance' at 0x7b4a94>
>>> ref() #调用它来访问被引用的对象
<socket.socketobject instance at 007B4A94>
一旦没有了对这个对象的其它的引用,调用弱引用将返回None,因为Python已经销毁了这个对象。 注意:大部分的对象不能通过弱引用来访问。
weakref模块中的getweakrefcount(obj)和getweakrefs(obj)分别返回弱引用数和关于所给对象的引用列表。
弱引用对于创建对象(这些对象很费资源)的缓存是有用的。
二、创建代理对象
代理对象是弱引用对象,它们的行为就像它们所引用的对象,这就便于你不必首先调用弱引用来访问背后的对象。通过weakref模块的proxy(obj[,callback])函数来创建代理对象。使用代理对象就如同使用对象本身一样:
>>> from socket import*
>>> import weakref
>>> s=socket(AF_INET,SOCK_STREAM)
>>> ref=weakref.proxy(s)
>>> s
<socket._socketobject instance at 007E4874>
>>> ref
<socket._socketobject instance at 007E4874>
>>> ref.close() #对象的方法同样工作
callback参数的目的和ref函数相同。在Python删除了一个引用的对象之后,使用代理将会导致一个weakref.ReferenceError错误:
>>> def s
>>> ref
Traceback (most recent call last):
File "<stdin>", line 1, in ?
弱引用使用的机会不是很多,一般用来进行 cache 编程。我们可以使用 weakref.ref() 来创建一个弱引用。
>>>>importsys
>>>importweakref
>>>classClass1:
deftest(self):
print"test..."
>>>o=Class1()
>>>sys.getrefcount(o)
2
>>>r=weakref.ref(o)#创建一个弱引用
>>>sys.getrefcount(o)#引用计数并没有改变
2
>>>r
<weakrefat00D3B3F0;to'instance'at00D37A30>#弱引用所指向的对象信息
>>>o2=r()#获取弱引用所指向的对象
>>>oiso2
True
>>>sys.getrefcount(o)
3
>>>o=None
>>>o2=None
>>>r#当对象引用计数为零时,弱引用失效。
<weakrefat00D3B3F0;dead>de>
weakref 还提供了一个 proxy():
importsys
importweakref
classClass1:
deftest(self):
print"test"
defcallback(self):
print"callback"
o=Class1()
p=weakref.proxy(o,callback)
p.test()
o=None
python的弱引用指引用一个对象但不增加它的引用计数器。这么做的好处是什么呢?什么时候需要考虑用若引用呢?
假设我们在设计一个游戏,有一个角色类Char,我们要给他添加一个效果(比如中毒),于是设计了一个效果类Effect。现在,给角色增加效果看上去就像这样:
char.effect=Effect()# 给角色添加一个效果
每个效果生效的时机都是不同的,为了方便复用,我们再设计一个激活策略类ActivePloy,负责激活效果。于是在Effect和ActivePloy的内部看上去就像这样:
classEffect(object):
def__init__(self):
self.active_ploy=ActivePloy(self)
defactive(self):
"""激活时的处理"""
pass
classActivePloy(object):
def__init__(self,effect):
self.effect=effect
defactive(self):
"""激活时,激活对应效果"""
self.effect.active()
这样做的好处是Effect不用关心自己何时激活,激活的判断都放给ActivePloy来处理。看上去挺好的,但是,这里面有一个问题,就是当我们试图给玩家去掉这个效果时……
delchar.effect
仔细想想,这么干以后,Effect的实例其实是没有被回收的,因为Effect和ActivePloy交叉引用,他们的引用计数都为1。
那么我们为了干净的删除effect,似乎就只能手动的来清理一下他们之间的这个交叉引用了:
classEffect(object):
def__init__(self):
self.active_ploy=ActivePloy(self)
defactive(self):
"""激活时的处理"""
pass
defdestroy(self):
self.active_ploy.destroy()
classActivePloy(object):
def__init__(self,effect):
self.effect=effect
defactive(self):
"""激活时,激活对应效果"""
self.effect.active()
defdestroy(self):
self.effect=None
于是我们要删除一个效果,就得这样:
char.effect.destroy()
delchar.effect
太麻烦了,不是吗?而且万一一个效果有多个激活策略的话,必须保证Effect把每个ActivePloy的destroy方法都运行一遍,漏了一个都无法保证自身被干净的删除。
我们来分析一下,之所以这么麻烦,就是因为ActivePloy对Effect有一个引用。那么如果ActivePloy不引用Effect不就OK了?这个时候,让我们来试试弱引用。
importweakref
classEffect(object):
def__init__(self):
self.active_ploy=ActivePloy(self)
defactive(self):
"""激活时的处理"""
pass
classActivePloy(object):
def__init__(self,effect):
self.effect=weakref.proxy(effect)#弱引用effect
defactive(self):
"""激活时,激活对应效果"""
self.effect.active()
代码只有一个地方改变了,就是
self.effect=weakref.proxy(effect)
这句的效果就是self.effect可以像往常一样的使用,但是却不会增加effect的引用计数器。换言之,这样写,他们之间的交叉关系消失了!这个时候我们只需要单纯的删掉char.effect,Effect和ActivePloy的实例都会被销毁。
什么,假设ActivePloy在其他地方也被引用了?这样当然只有effect会被销毁。但是我们想让ActivePloy必然随着Effect的销毁而销毁,怎么办呢?那么我们可以改改,给弱引用加上一个回调函数:
classActivePloy(object):
def__init__(self,effect):
self.effect=weakref.proxy(effect,self.on_effect_destroy)#弱引用effect
defactive(self):
"""激活时,激活对应效果"""
self.effect.active()
defon_effect_destroy(self,effect):
"""
effect销毁时会调用这个方法,在这里把对自己的引用都清理干净吧
"""
pass
这样一来,就不用担心删不干净了。

Ⅳ 如何用python添加perforce文件

一 p4的API支持几乎所有的常用的语言
1)查看p4 API 主页
2)支持几乎所有的语言:
Perforce C/C++ API
Perforce Java API
Perforce Perl API
Perforce Ruby API
Perforce Python API
Perforce PHP API
Perforce Objective-C API
P4COM, a COM Interface to the Perforce C++ API for Windows

二 p4python
1)安装(以windows为例)
下载和安装python2.6;(可以安装activepython)
下载和安装p4python26;(ftp://ftp.perforce.com/perforce/r09.2/bin.ntx86/p4python26.exe)
2)安装后(C:\Python26\Lib\site-packages)
文件:P4.py + P4.pyc + P4API.pyd + P4Python-2009.2-py2.6.egg-info。其中P4API.pyd为python对p4的extension模块,里面定义了 P4API.P4Adapter可惜看不到源码,P4.py 里面包含了p4 class的定义,p4class从P4API.P4Adapter继承。
3)p4.py
在p4.py中定义了
• P4
• P4Exception
• DepotFile
• Revision
• Integration
• MergeData
• Spec
其中主要的p4 class定义如下:
import P4API

class P4(P4API.P4Adapter):
"""Use this class to communicate with a Perforce server

Instances of P4 will use the environment settings (including P4CONFIG)
to determine the connection parameters such as P4CLIENT and P4PORT.

This attributes can also be set separately before connecting.

To run any Perforce commands, users of this class first need to run
the connect() method.

It is good practice to disconnect() after the program is complete.
"""
# Constants useful for exception_level
# RAISE_ALL: Errors and Warnings are raised as exceptions (default)
# RAISE_ERROR: Only Errors are raised as exceptions
# RAISE_NONE: No exceptions are raised, instead False is returned

RAISE_ALL = 2
RAISE_ERROR = 1
RAISE_NONE = 0

def __init__(self, *args, **kwlist):
P4API.P4Adapter.__init__(self, *args, **kwlist)

def __del__(self):
if self.debug > 3:
print >>sys.stderr, "P4.__del__()"

# store the references to the created lambdas as a weakref to allow Python
# to clean up the garbage. |The lambda as a closure stores a reference to self
# which causes a circular reference problem without the weakref

def __getattr__(self, name):
if name.startswith("run_"):
cmd = name[len("run_"):]
return lambda *args: self.run(cmd, *args)
elif name.startswith("delete_"):
cmd = name[len("delete_"):]
return lambda *args: self.run(cmd, "-d", *args)
elif name.startswith("fetch_"):
cmd = name[len("fetch_"):]
return lambda *args: self.run(cmd, "-o", *args)[0]
elif name.startswith("save_"):
cmd = name[len("save_"):]
return lambda *args: self.__save(cmd, *args)
elif name.startswith("parse_"):
cmd = name[len("parse_"):]
return lambda *args: self.parse_spec(cmd, *args)
elif name.startswith("format_"):
cmd = name[len("format_"):]
return lambda *args: self.format_spec(cmd, *args)
else:
raise AttributeError, name

def __save(self, cmd, *args):
self.input = args[0]
return self.run(cmd, "-i", args[1:])

def __repr__(self):
state = "disconnected"
if self.connected():
state = "connected"

return "P4 [%s@%s %s] %s" % \
(self.user, self.client, self.port, state)

def identify(cls):
return P4API.identify()
identify = classmethod(identify)

def run(self, *args):
"Generic run method"
return P4API.P4Adapter.run(self, *self.__flatten(args))

def run_submit(self, *args):
"Simplified submit - if any arguments is a dict, assume it to be the changeform"
nargs = list(args)
form = None
for n, arg in enumerate(nargs):
if isinstance( arg, dict):
self.input = arg
nargs.pop(n)
nargs.append("-i")
break
return self.run("submit", *nargs)

def run_login(self, *args):
"Simple interface to make login easier"
self.input = self.password
return self.run("login", *args)

def run_password( self, oldpass, newpass ):
"Simple interface to allow setting of the password"
if( oldpass and len(oldpass) > 0 ):
self.input = [ oldpass, newpass, newpass ]
else:
self.input = [ newpass, newpass ]

return self.run( "password" )

#
# run_filelog: convert "p4 filelog" responses into objects with useful
# methods
#
# Requires tagged output to be of any real use. If tagged output it not
# enabled then you just get the raw data back
#
def run_filelog( self, *args ):
raw = self.run( 'filelog', args )
if (not self.tagged):
# untagged mode returns simple strings, which breaks the code below
return raw
result = []
for h in raw:
r = None
if isinstance( h, dict ):
df = DepotFile( h[ "depotFile" ] )
for n, rev in enumerate( h[ "rev" ]):
# Create a new revision of this file ready for populating
r = df.new_revision()
# Populate the base attributes of each revision
r.rev = int( rev )
r.change = int( h[ "change" ][ n ] )
r.action = h[ "action" ][ n ]
r.type = h[ "type" ][ n ]
r.time = datetime.datetime.utcfromtimestamp( int( h[ "time" ][ n ]) )
r.user = h[ "user" ][ n ]
r.client = h[ "client" ][ n ]
r.desc = h[ "desc" ][ n ]
if "digest" in h:
r.digest = h[ "digest" ][ n ]
if "fileSize" in h:
r.fileSize = h[ "fileSize" ][ n ]

# Now if there are any integration records for this revision,
# add them in too

if (not "how" in h) or (n >= len(h["how"]) or h["how"][n] == None):
continue
else:
for m, how in enumerate( h[ "how" ][ n ] ):
file = h[ "file" ][ n ][ m ]
srev = string.lstrip(h[ "srev" ][ n ][ m ], '#')
erev = string.lstrip(h[ "erev" ][ n ][ m ], '#')

if srev == "none":
srev = 0
else:
srev = int( srev )

if erev == "none":
erev = 0
else:
erev = int( erev )

r.integration( how, file, srev, erev )
else:
r = h
result.append( df )
return result

def run_print(self, *args):
raw = self.run('print', args)
result = [raw.pop(0), ""]

for line in raw:
result[-1] += line
return result

def run_resolve(self, *args, **kargs):
myResolver = Resolver()
if "resolver" in kargs:
myResolver = kargs["resolver"]

savedResolver = self.resolver
self.resolver = myResolver
result = self.run("resolve", args)
self.resolver = savedResolver

return result

def __flatten(self, args):
result = []
if isinstance(args, tuple) or isinstance(args, list):
for i in args:
result.extend(self.__flatten(i))
else:
result.append(args)
return tuple(result)

def __enter__( self ):
return self

def __exit__( self, exc_type, exc_val, exc_tb ):
if self.connected():
self.disconnect()
return True

def connect( self ):
P4API.P4Adapter.connect( self )
return self

@contextmanager
def while_tagged( self, t ):
old = self.tagged
self.tagged = t
yield
self.tagged = old

@contextmanager
def at_exception_level( self, e ):
old = self.exception_level
self.exception_level = e
yield
self.exception_level = old

@contextmanager
def saved_context( self , **kargs):
"""Saves the context of this p4 object and restores it again at the end of the block"""

saved_context = {}
for attr in self.__members__:
saved_context[attr] = getattr(self, attr)

for (k,v) in kargs.items():
setattr( self, k, v)

yield

# now restore the context again. Ignore AttributeError exception
# Exception is expected because some attributes only have getters, no setters

for (k,v) in saved_context.items():
try:
setattr( self, k, v )
except AttributeError:
pass # expected for server_level and p4config_file

三 实例
1)p4info.py
from P4 import P4,P4Exception

p4 = P4()
p4.port = "localhost:1666"
p4.user = "AAA"
p4.password = "aaa"
p4.client = "TestProject_AAA"

try:
p4.connect()
info = p4.run("info")
for key in info[0]:
print key, "=", info[0][key]
p4.disconnect()
except P4Exception:
for e in p4.errors:
print e
结果:

2)p4sync.py
from P4 import P4, P4Exception

p4 = P4()
p4.port = "localhost:1666"
p4.user = "AAA"
p4.password = "aaa"
p4.client = "TestProject_AAA"

try:
p4.connect()
p4.exception_level = 1 # ignore "File(s) up-to-date"
files = p4.run_sync()
for file in files:
for key in file.keys():
print key,":",file[key]
print "----------"
except P4Exception:
for e in p4.errors:
print e
finally:
p4.disconnect()
结果:

3)p4submit.py
from P4 import P4

p4 = P4()
p4.host = "localhost"
p4.port = "1666"
p4.user = "AAA"
p4.password = "aaa"
p4.client = "TestProject_AAA"

p4.connect()
changeSpec = p4.run_change( "-o" )
change = changeSpec[0]
change["Description"] = "Autosubmitted changelist"

p4.run_edit("//depot/TestProject/addfile.txt")

change["Files"] = ["//depot/TestProject/addfile.txt"]
p4.input = change
p4.run_submit( "-i" )
p4.disconnect()

Ⅳ Python自定义的类,为什么需要重写

首先,自定义的类在不继承任何基类的情况下,也具有__str__属性:

[python] view plain
class RoundFloatManual(object):
... def __init__(self, val):
... assert isinstance(val, float), \
... "Value must be a float!"
... self.value = round(val, 2)
rfm = RoundFloatManual(5.590464)
dir(rfm)

返回:
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__mole__', '__new__', '__rece__', '__rece_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'value']
__str__ 是 Python 类中的特殊方法,他的回传值就是使用 str(x) 所得到的值, 而 print(x) 其实就等于是print(str(x)).其实再讲细一点,当我们呼叫 str(x) 的时候其实是呼叫x.__str__()
也就是说我们可以这样想象:

print(x) === print(str(x)) === print(x.__str__())
一般我们 自定义的类,__str__ 方法的回传值是默认的字串,比如说: <__main__.Mylist object at 0x0071A470> 用以说明 namespace, class name 和位置.如果要改变__str__ 的回传值,我们必须要覆写他.

Ⅵ python类里的私有变量如何定义

python没有私有变量,任何定义的变量都是可以直接调用的,但是一般来说,在定义的变量前后加上两个下划线,把这样的变量当成是私有变量,如下代码所示:

classperson:
def__init__(self):
self.__private__=100
p=person()
print('__private__:',p.__private__)
print('p包含的变量:',dir(p))

输出:

__private__:100
p包含的变量:['__class__','__delattr__','__dict__','__dir__','__doc__','__eq__','__format__','__ge__','__getattribute__','__gt__','__hash__','__init__','__le__','__lt__','__mole__','__ne__','__new__','__private__','__rece__','__rece_ex__','__repr__','__setattr__','__sizeof__','__str__','__subclasshook__','__weakref__']

Ⅶ c与python之间传递特殊字符

>>> from ctypes import *
>>> libc=cdll.msvcrt
>>> libc.printf("hello %s\n","world")
hello world
12
>>>

>>> p = create_string_buffer("Hello", 30)
>>> n=libc.sprintf(p,"hello %s\n","world")
>>> n
12
>>> print p
<ctypes.c_char_Array_30 object at 0x02247C10>
>>> dir(p)
['__class__', '__ctypes_from_outparam__', '__delattr__', '__delitem__', '__delsl
ice__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__',
'__getslice__', '__hash__', '__init__', '__len__', '__mole__', '__new__', '__r
ece__', '__rece_ex__', '__repr__', '__setattr__', '__setitem__', '__setslice
__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'_b_base_', '_b_needsfree_', '_length_', '_objects', '_type_', 'raw', 'value']
>>> p.value
'hello world\n'
>>>

Ⅷ python怎么测试与redis的连接

Redis服务端:192.168.100.132;port=6379
Redis客户端:192.168.100.132
客户端操作:
安装python支持redis;
tar zxvf redis-2.9.1.tar.gz
cd redis-2.9.1
python setup.py install
服务端启动redis
/root/redis-2.2.12/src/redis-server
客户端测试:
[root@master ~]# python
>>> import redis
>>> r = redis.Redis(host='192.168.100.132',port=6379,db=0) //#如果设置了密码,就加上password=密码
>>> r.set('name','lansgg')
True
>>> r.get('name')
'lansgg'
>>> r.exists('name') //#看是否存在这个键值
True
>>> r.delete('name')
1
>>> r.dbsize() //#库里有多少key,多少条数据
0L
>>> r.set('name','lansgg')
True
>>> r.flushdb() // #删除当前数据库的所有数据
True
>>> r.get('name')
>>> r.set('name','lansgg')
True
>>> r.set('wm','leo')
True
>>> r.set('tt','coffee')
True
>>> r.keys() // # 列出所有键值。
['tt', 'wm', 'name']
>>> r.save() // #强行把数据库保存到硬盘。保存时阻塞
True
>>> r.dbsize()
3L
>>> dir(r)
['RESPONSE_CALLBACKS', '__class__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__mole__', '__new__', '__rece__', '__rece_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_zaggregate', 'append', 'bgrewriteaof', 'bgsave', 'bitcount', 'bitop', 'blpop', 'brpop', 'brpoplpush', 'client_getname', 'client_kill', 'client_list', 'client_setname', 'config_get', 'config_resetstat', 'config_set', 'connection_pool', 'dbsize', 'debug_object', 'decr', 'delete', 'mp', 'echo', 'eval', 'evalsha', 'execute_command', 'exists', 'expire', 'expireat', 'flushall', 'flushdb', 'from_url', 'get', 'getbit', 'getrange', 'getset', 'hdel', 'hexists', 'hget', 'hgetall', 'hincrby', 'hincrbyfloat', 'hkeys', 'hlen', 'hmget', 'hmset', 'hscan', 'hset', 'hsetnx', 'hvals', 'incr', 'incrby', 'incrbyfloat', 'info', 'keys', 'lastsave', 'lindex', 'linsert', 'llen', 'lock', 'lpop', 'lpush', 'lpushx', 'lrange', 'lrem', 'lset', 'ltrim', 'mget', 'move', 'mset', 'msetnx', 'object', 'parse_response', 'persist', 'pexpire', 'pexpireat', 'ping', 'pipeline', 'psetex', 'pttl', 'publish', 'pubsub', 'randomkey', 'register_script', 'rename', 'renamenx', 'response_callbacks', 'restore', 'rpop', 'rpoplpush', 'rpush', 'rpushx', 'sadd', 'save', 'scan', 'scard', 'script_exists', 'script_flush', 'script_kill', 'script_load', 'sdiff', 'sdiffstore', 'sentinel', 'sentinel_get_master_addr_by_name', 'sentinel_masters', 'sentinel_sentinels', 'sentinel_slaves', 'set', 'set_response_callback', 'setbit', 'setex', 'setnx', 'setrange', 'shutdown', 'sinter', 'sinterstore', 'sismember', 'slaveof', 'smembers', 'smove', 'sort', 'spop', 'srandmember', 'srem', 'sscan', 'strlen', 'substr', 'sunion', 'sunionstore', 'time', 'transaction', 'ttl', 'type', 'unwatch', 'watch', 'zadd', 'zcard', 'zcount', 'zincrby', 'zinterstore', 'zrange', 'zrangebyscore', 'zrank', 'zrem', 'zremrangebyrank', 'zremrangebyscore', 'zrevrange', 'zrevrangebyscore', 'zrevrank', 'zscan', 'zscore', 'zunionstore']
这只是一个简单的测试,为了测试redis是否正常工作,我们安装是否正确;

Ⅸ Java,Python之类的有智能指针的语言,如何处理由交叉引用造成的内存泄漏

正常设计通常不会有交叉引用的问题。 别被这些东西困扰了。

比如上面设计中,引用对象,通常是因为这些对象是父类,或者是功能类,所以当前类被删除的时候并不会被删除,但是父类和功能类通常都在系统初始化时初始化,系统退出时才被删除。

所以正常的设计情况下不存在这个问题。 内存泄漏往往是在使用别人的类,又不太搞清楚它的位置以及使用方法的情况下造成的。

Ⅹ python中flask如何降低内存

Dict
在小型程序中,特别是在脚本中,使用Python自带的dict来表示结构信息非常简单方便:

>>> ob = {'x':1, 'y':2, 'z':3}

>>> x = ob['x']

>>> ob['y'] = y

由于在Python 3.6中dict的实现采用了一组有序键,因此其结构更为紧凑,更深得人心。但是,让我们看看dict在内容中占用的空间大小:

>>> print(sys.getsizeof(ob))

240

如上所示,dict占用了大量内存,尤其是如果突然虚需要创建大量实例时:

实例数

对象大小

1 000 000

240 Mb

10 000 000

2.40 Gb

100 000 000

24 Gb

类实例

有些人希望将所有东西都封装到类中,他们更喜欢将结构定义为可以通过属性名访问的类:

class Point:

#

def __init__(self, x, y, z):

self.x = x

self.y = y

self.z = z

>>> ob = Point(1,2,3)

>>> x = ob.x

>>> ob.y = y

类实例的结构很有趣:

字段

大小(比特)

PyGC_Head

24

PyObject_HEAD

16

__weakref__

8

__dict__
8

合计:

56

在上表中,__weakref__是该列表的引用,称之为到该对象的弱引用(weak reference);字段__dict__是该类的实例字典的引用,其中包含实例属性的值(注意在64-bit引用平台中占用8字节)。从Python3.3开始,所有类实例的字典的键都存储在共享空间中。这样就减少了内存中实例的大小:

>>> print(sys.getsizeof(ob), sys.getsizeof(ob.__dict__))

56 112

因此,大量类实例在内存中占用的空间少于常规字典(dict):

实例数

大小

1 000 000
168 Mb
10 000 000
1.68 Gb
100 000 000

16.8 Gb

不难看出,由于实例的字典很大,所以实例依然占用了大量内存。

带有__slots__的类实例

为了大幅降低内存中类实例的大小,我们可以考虑干掉__dict__和__weakref__。为此,我们可以借助 __slots__:

class Point:

__slots__ = 'x', 'y', 'z'

def __init__(self, x, y, z):

self.x = x

self.y = y
self.z = z
>>> ob = Point(1,2,3)
>>> print(sys.getsizeof(ob))

64

如此一来,内存中的对象就明显变小了:

字段

大小(比特)

PyGC_Head

24

PyObject_HEAD
16
x
8

y

8
z
8
总计:

64

在类的定义中使用了__slots__以后,大量实例占据的内存就明显减少了:

实例数

大小

1 000 000

64 Mb

10 000 000

640 Mb

100 000 000
6.4 Gb
目前,这是降低类实例占用内存的主要方式。
这种方式减少内存的原理为:在内存中,对象的标题后面存储的是对象的引用(即属性值),访问这些属性值可以使用类字典中的特殊描述符:

>>> pprint(Point.__dict__)

mappingproxy(

....................................

'x': ,

'y': ,

'z': })

为了自动化使用__slots__创建类的过程,你可以使用库namedlist(https://pypi.org/project/namedlist)。namedlist.namedlist函数可以创建带有__slots__的类:

>>> Point = namedlist('Point', ('x', 'y', 'z'))

还有一个包attrs(https://pypi.org/project/attrs),无论使用或不使用__slots__都可以利用这个包自动创建类。

元组

Python还有一个自带的元组(tuple)类型,代表不可修改的数据结构。元组是固定的结构或记录,但它不包含字段名称。你可以利用字段索引访问元组的字段。在创建元组实例时,元组的字段会一次性关联到值对象:

>>> ob = (1,2,3)

>>> x = ob[0]

>>> ob[1] = y # ERROR

元组实例非常紧凑:

>>> print(sys.getsizeof(ob))

72

由于内存中的元组还包含字段数,因此需要占据内存的8个字节,多于带有__slots__的类:

字段

大小(字节)

PyGC_Head

24

PyObject_HEAD

16

ob_size

8

[0]

8

[1]

8

[2]
8
总计:
72
命名元组

由于元组的使用非常广泛,所以终有一天你需要通过名称访问元组。为了满足这种需求,你可以使用模块collections.namedtuple。

namedtuple函数可以自动生成这种类:

>>> Point = namedtuple('Point', ('x', 'y', 'z'))

如上代码创建了元组的子类,其中还定义了通过名称访问字段的描述符。对于上述示例,访问方式如下:
class Point(tuple):
#

@property

def _get_x(self):

return self[0]
@property
def _get_y(self):

return self[1]

@property

def _get_z(self):
return self[2]
#
def __new__(cls, x, y, z):
return tuple.__new__(cls, (x, y, z))
这种类所有的实例所占用的内存与元组完全相同。但大量的实例占用的内存也会稍稍多一些:

实例数

大小
1 000 000
72 Mb

10 000 000

720 Mb

100 000 000

7.2 Gb

记录类:不带循环GC的可变更命名元组

由于元组及其相应的命名元组类能够生成不可修改的对象,因此类似于ob.x的对象值不能再被赋予其他值,所以有时还需要可修改的命名元组。由于Python没有相当于元组且支持赋值的内置类型,因此人们想了许多办法。在这里我们讨论一下记录类(recordclass,https://pypi.org/project/recordclass),它在StackoverFlow上广受好评(https://stackoverflow.com/questions/29290359/existence-of-mutable-named-tuple-in)。

此外,它还可以将对象占用的内存量减少到与元组对象差不多的水平。

recordclass包引入了类型recordclass.mutabletuple,它几乎等价于元组,但它支持赋值。它会创建几乎与namedtuple完全一致的子类,但支持给属性赋新值(而不需要创建新的实例)。recordclass函数与namedtuple函数类似,可以自动创建这些类:

>>>Point = recordclass('Point', ('x', 'y', 'z'))

>>>ob = Point(1, 2, 3)

类实例的结构也类似于tuple,但没有PyGC_Head:

字段

大小(字节)

PyObject_HEAD

16

ob_size

8

x

8

y

8

z
8
总计:
48
在默认情况下,recordclass函数会创建一个类,该类不参与垃圾回收机制。一般来说,namedtuple和recordclass都可以生成表示记录或简单数据结构(即非递归结构)的类。在Python中正确使用这二者不会造成循环引用。因此,recordclass生成的类实例默认情况下不包含PyGC_Head片段(这个片段是支持循环垃圾回收机制的必需字段,或者更准确地说,在创建类的PyTypeObject结构中,flags字段默认情况下不会设置Py_TPFLAGS_HAVE_GC标志)。

大量实例占用的内存量要小于带有__slots__的类实例:

实例数

大小

1 000 000

48 Mb10 000 000

480 Mb

100 000 000
4.8 Gb
dataobject
recordclass库提出的另一个解决方案的基本想法为:内存结构采用与带__slots__的类实例同样的结构,但不参与循环垃圾回收机制。这种类可以通过recordclass.make_dataclass函数生成:
>>> Point = make_dataclass('Point', ('x', 'y', 'z'))

这种方式创建的类默认会生成可修改的实例。

另一种方法是从recordclass.dataobject继承:

class Point(dataobject):

x:int

y:int

z:int

这种方法创建的类实例不会参与循环垃圾回收机制。内存中实例的结构与带有__slots__的类相同,但没有PyGC_Head:

字段

大小(字节)

PyObject_HEAD

16

ob_size

8

x

8

y

8

z

8

总计:

48

>>> ob = Point(1,2,3)

>>> print(sys.getsizeof(ob))

40

如果想访问字段,则需要使用特殊的描述符来表示从对象开头算起的偏移量,其位置位于类字典内:

mappingproxy({'__new__': ,

.......................................

'x': ,

'y': ,

'z': })

大量实例占用的内存量在CPython实现中是最小的:

实例数

大小

1 000 000

40 Mb

10 000 000

400 Mb

100 000 000

4.0 Gb

Cython

还有一个基于Cython(https://cython.org/)的方案。该方案的优点是字段可以使用C语言的原子类型。访问字段的描述符可以通过纯Python创建。例如:

cdef class Python:

cdef public int x, y, z

def __init__(self, x, y, z):

self.x = x

self.y = y

self.z = z

本例中实例占用的内存更小:

>>> ob = Point(1,2,3)

>>> print(sys.getsizeof(ob))

32

内存结构如下:

字段

大小(字节)

热点内容
创建邮箱地址服务器连接错误 发布:2025-01-13 09:49:24 浏览:723
linux编辑文档 发布:2025-01-13 09:47:51 浏览:435
二手制冷压缩机 发布:2025-01-13 09:43:59 浏览:585
网鱼电脑密码多少 发布:2025-01-13 09:33:46 浏览:464
如何取消子账号密码 发布:2025-01-13 09:22:41 浏览:347
抖音搜索有缓存 发布:2025-01-13 09:17:28 浏览:590
c语言字符数组连接 发布:2025-01-13 08:55:11 浏览:901
国二c语言编程题目 发布:2025-01-13 08:45:41 浏览:285
ipad软件如何加密 发布:2025-01-13 08:28:59 浏览:278
android的文件操作 发布:2025-01-13 08:24:48 浏览:173