當前位置:首頁 » 編程語言 » 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 07:16:06 瀏覽:982
php字元串浮點數 發布:2025-01-13 07:15:28 瀏覽:997
python排序cmp 發布:2025-01-13 07:09:04 瀏覽:71
雲腳本精靈 發布:2025-01-13 07:03:27 瀏覽:617
高維訪問 發布:2025-01-13 07:03:23 瀏覽:974
保衛蘿卜有腳本嗎 發布:2025-01-13 06:30:29 瀏覽:741
天貓上傳 發布:2025-01-13 06:06:35 瀏覽:156
php處理並發 發布:2025-01-13 06:03:44 瀏覽:282
安卓傳文件的軟體哪個最好 發布:2025-01-13 06:03:07 瀏覽:885
電腦伺服器可以做嗎 發布:2025-01-13 05:59:49 瀏覽:846