سؤال

أحتاج إلى تمثيل مضغوط لمجموعة من القيم المنطقية، هل لدى Python نوع حقل بت مدمج أم سأحتاج إلى إيجاد حل بديل؟

هل كانت مفيدة؟

المحلول

بيتاراي كانت أفضل إجابة وجدتها، عندما كانت لدي مؤخرًا حاجة مماثلة.إنه امتداد C (أسرع بكثير من BitVector، وهو بيثون خالص) ويخزن بياناته في حقل بت فعلي (لذا فهو أكثر كفاءة في الذاكرة بثمانية أضعاف من المصفوفة المنطقية التي يبدو أنها تستخدم بايت لكل عنصر.)

نصائح أخرى

إذا كنت تريد بشكل أساسي أن تكون قادرًا على تسمية حقول البت الخاصة بك ومعالجتها بسهولة، على سبيل المثال.للعمل مع العلامات الممثلة كبتات مفردة في بروتوكول الاتصالات، يمكنك استخدام ميزات الهيكل والاتحاد القياسية الخاصة بـ com.ctypes, ، كما هو موضح في كيف يمكنني الإعلان بشكل صحيح عن بنية ctype + Union في بايثون؟- تجاوز سعة المكدس

على سبيل المثال، للعمل مع البتات الأربعة الأقل أهمية من البايت بشكل فردي، ما عليك سوى تسميتها من الأقل إلى الأكثر أهمية في LittleEndianStructure.يمكنك استخدام اتحاد لتوفير الوصول إلى نفس البيانات مثل البايت أو int حتى تتمكن من نقل البيانات داخل أو خارج بروتوكول الاتصال.وفي هذه الحالة يتم ذلك عن طريق flags.asbyte مجال:

import ctypes
c_uint8 = ctypes.c_uint8

class Flags_bits(ctypes.LittleEndianStructure):
    _fields_ = [
            ("logout", c_uint8, 1),
            ("userswitch", c_uint8, 1),
            ("suspend", c_uint8, 1),
            ("idle", c_uint8, 1),
        ]

class Flags(ctypes.Union):
    _fields_ = [("b", Flags_bits),
                ("asbyte", c_uint8)]

flags = Flags()
flags.asbyte = 0xc

print(flags.b.idle)
print(flags.b.suspend)
print(flags.b.userswitch)
print(flags.b.logout)

البتات الأربع (التي طبعتها هنا بدءًا من البتات الأكثر أهمية، والتي تبدو أكثر طبيعية عند الطباعة) هي 1، 1، 0، 0، أي.0xc في ثنائي.

يجب عليك إلقاء نظرة على bitstring الوحدة، والتي وصلت مؤخرًا إلى الإصدار 2.0.يتم تخزين البيانات الثنائية بشكل مضغوط كمصفوفة بايت ويمكن إنشاؤها وتعديلها وتحليلها بسهولة.

ثستطيع ان تخلق BitString كائنات من ثنائي وثماني وعرافة وأعداد صحيحة (كبيرة أو صغيرة) وسلاسل وبايتات وعائمات وملفات والمزيد.

a = BitString('0xed44')
b = BitString('0b11010010')
c = BitString(int=100, length=14)
d = BitString('uintle:16=55, 0b110, 0o34')
e = BitString(bytes='hello')
f = pack('<2H, bin:3', 5, 17, '001') 

يمكنك بعد ذلك تحليلها وتعديلها باستخدام وظائف بسيطة أو تدوين شرائح - لا داعي للقلق بشأن أقنعة البت وما إلى ذلك.

a.prepend('0b110')
if '0b11' in b:
    c.reverse()
g = a.join([b, d, e])
g.replace('0b101', '0x3400ee1')
if g[14]:
    del g[14:17]
else:
    g[55:58] = 'uint:11=33, int:9=-1'

هناك أيضًا مفهوم موضع البت، بحيث يمكنك التعامل معه كملف أو دفق إذا كان ذلك مفيدًا لك.تُستخدم الخصائص لإعطاء تفسيرات مختلفة لبيانات البت.

w = g.read(10).uint
x, y, z = g.readlist('int:4, int:4, hex:32')
if g.peek(8) == '0x00':
    g.pos += 10

بالإضافة إلى أن هناك دعمًا للمشغلين الثنائيين القياسيين، والتعبئة، والتفريغ، والنهاية، والمزيد.أحدث إصدار مخصص لـ Python 2.7 و3.x، وعلى الرغم من أنه Python خالص، إلا أنه تم تحسينه بشكل جيد من حيث الذاكرة والسرعة.

أستخدم عوامل البت الثنائية !، &، |، ^، >>، و <<.إنها تعمل بشكل جيد ويتم تنفيذها مباشرة في لغة C الأساسية، والتي عادة ما تكون مباشرة على الأجهزة الأساسية.

قم بتمثيل كل قيمة من قيمك كقوة لاثنين:

testA = 2**0
testB = 2**1
testC = 2**3

ثم لتعيين قيمة صحيحة:

table = table | testB

لتعيين قيمة خاطئة:

table = table & (~testC)

لاختبار القيمة:

bitfield_length = 0xff
if ((table & testB & bitfield_length) != 0):
    print "Field B set"

تعمق قليلاً في التمثيل السداسي العشري إذا لم يكن هذا منطقيًا بالنسبة لك.هذه هي الطريقة الأساسية لتتبع العلامات المنطقية في تطبيق C المضمن أيضًا (إذا كانت لديك ذاكرة محدودة).

قد تكون حزمة BitVector هي ما تحتاجه.إنه ليس مدمجًا في تثبيت python الخاص بي، ولكن من السهل تعقبه على موقع python.

https://pypi.python.org/pypi/BitVector للنسخة الحالية.

NumPy لديه واجهة المصفوفة الوحدة النمطية التي يمكنك استخدامها لإنشاء حقل bitfield.

إذا كان حقل البت الخاص بك قصيرًا، فمن المحتمل أن تستخدمه وحدة الهيكل.وإلا فإنني أوصي بنوع من الغلاف وحدة المصفوفة.

أيضًا، تحتوي وحدة ctypes على حقول البت, ، لكنني لم أستخدمها بنفسي أبدًا. مسؤولية المشتري.

إذا كنت تريد استخدام ints (أو ints long) لتمثيلها كمصفوفات من المنطقيات (أو كمجموعات من الأعداد الصحيحة)، فقم بإلقاء نظرة على http://sourceforge.net/projects/pybitop/files/

يوفر إدراج/استخراج حقول البت في ints الطويلة؛العثور على البت "1" الأكثر أهمية أو الأقل أهمية؛عد كل 1؛عكس البت؛أشياء مثل تلك التي هي كلها ممكنة في لغة بايثون النقية ولكنها أسرع بكثير في لغة C.

بالنسبة للبتات المتتالية في الغالب، يوجد ملف https://pypi.org/project/range_set/ الوحدة النمطية التي تتوافق مع واجهة برمجة التطبيقات (API) مع لغة Python المدمجة set.كما يوحي الاسم، فإنه يخزن البتات كأزواج بداية/نهاية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top