gpt4 book ai didi

python - 创建 'generic' 类继承外部模块类的最佳方法

转载 作者:太空宇宙 更新时间:2023-11-04 07:07:35 24 4
gpt4 key购买 nike

ctypes 模块中,底层 c_* 类型执行 C 风格的截断而不引发任何异常。例如,c_uint8(0x120)c_uint8(0x20) 相同,后者与 c_uint8(32) 相同。我希望创建继承 ctypes 类型的类,如果类型超出其范围,这些类将引发自定义异常。这是我到目前为止想出的:

from ctypes import *

class C_U8(c_uint8):
def __init__(self, value):
if value < 0 or value > 0xFF:
raise Exception("Nice try! Out of range")

虽然这按预期工作,但我很快意识到,为每个 ctypes 类型编写这将成为一个相当多余的类。我想知道是否有更好的方法来做到这一点,例如创建一个从 ctypes 模块继承所有类型的泛型类,并相应地对每种类型进行边界检查?

最佳答案

这是一种使用类工厂函数来实现的方法。您向函数传递一个 ctypes 数据类型类和所需的边界,它返回一个新类,该类在创建实例或其 .value 属性更新时强制执行边界。

我只在 Python 2.6.6 上测试过这段代码,但它应该可以在 Python 3 上运行(一旦你修复了 main() 中的 print 语句)。

#!/usr/bin/env python

''' Bounded ctypes integer classes

Derive bounded versions of the ctypes integer datatype classes

For http://stackoverflow.com/q/31317553/4014959

Written by PM 2Ring 2015.07.10
'''

import ctypes
import sys

bounds_info = (
('c_byte', -2**7, 2**7-1),
('c_int', -2**31, 2**31-1),
('c_int16', -2**15, 2**15-1),
('c_int32', -2**31, 2**31-1),
('c_int64', -2**63, 2**63-1),
('c_int8', -2**7, 2**7-1),
('c_long', -2**31, 2**31-1),
('c_longlong', -2**63, 2**63-1),
('c_short', -2**15, 2**15-1),
('c_ubyte', 0, 2**8-1),
('c_uint', 0, 2**32-1),
('c_uint16', 0, 2**16-1),
('c_uint32', 0, 2**32-1),
('c_uint64', 0, 2**64-1),
('c_uint8', 0, 2**8-1),
('c_ulong', 0, 2**32-1),
('c_ulonglong', 0, 2**64-1),
('c_ushort', 0, 2**16-1),
)

def bounded_ctypes_class(name, lo, hi):
''' Derive a bounded version of a named ctypes integer class '''
parent = getattr(ctypes, name)
class Bint(parent):
def __init__(self, value=0):
if lo <= value <= hi:
super(Bint, self).__init__(value)
else:
raise ValueError, (
'Out of bounds: %s initial value %d is not between %d & %d'
% (self, value, lo, hi))

def __setattr__(self, attr, value):
#print "%s setattr('%s', %s) called" % (self, attr, value)
if attr == 'value' and not self._lolim <= value <= self._hilim:
raise ValueError, (
'Out of bounds: %s update value %d is not between %d & %d'
% (self, value, lo, hi))
super(Bint, self).__setattr__(attr, value)

newname = 'b' + name
Bint.__name__ = newname
Bint._lolim = lo
Bint._hilim = hi
return Bint


#Create the bounded classes
def create_classes():
module = sys.modules[__name__]
for name, lo, hi in bounds_info:
cls = bounded_ctypes_class(name, lo, hi)
setattr(module, cls.__name__, cls)


#Test the bounded classes
def main():
module = sys.modules[__name__]
for name, lo, hi in bounds_info:
newname = 'b' + name
cls = getattr(module, newname)
print 'Testing', cls
good = lo + 3 * (hi - lo) // 4
for v in (good, lo-1, hi+1):
try:
print 'Initializing with\n%d' % v
a = cls(v)
print a.value
a.value += 1
print a.value
a.value += hi
print a.value
except Exception as e:
print e

print

print 40 * '- ' + '\n'

#A test with "normal" instance creation syntax.
a = bc_byte(7); print a, a.value
a.value += 100; print a.value
try:
a.value += 30; print a.value
except Exception as e:
print e


create_classes()

if __name__ == '__main__':
main()

这是输出的最后一个屏幕左右:

Testing <class '__main__.bc_ulong'>
Initializing with
3221225471
3221225471
3221225472
Out of bounds: <bc_ulong object at 0xb732d3d4> update value 7516192767 is not between 0 & 4294967295

Initializing with
-1
Out of bounds: <bc_ulong object at 0xb732d38c> initial value -1 is not between 0 & 4294967295

Initializing with
4294967296
Out of bounds: <bc_ulong object at 0xb732d4ac> initial value 4294967296 is not between 0 & 4294967295

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Testing <class '__main__.bc_ulonglong'>
Initializing with
13835058055282163711
13835058055282163711
13835058055282163712
Out of bounds: <bc_ulonglong object at 0xb732d38c> update value 32281802128991715327 is not between 0 & 18446744073709551615

Initializing with
-1
Out of bounds: <bc_ulonglong object at 0xb732d4ac> initial value -1 is not between 0 & 18446744073709551615

Initializing with
18446744073709551616
Out of bounds: <bc_ulonglong object at 0xb732d3d4> initial value 18446744073709551616 is not between 0 & 18446744073709551615

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Testing <class '__main__.bc_ushort'>
Initializing with
49151
49151
49152
Out of bounds: <bc_ushort object at 0xb732d4ac> update value 114687 is not between 0 & 65535

Initializing with
-1
Out of bounds: <bc_ushort object at 0xb732d3d4> initial value -1 is not between 0 & 65535

Initializing with
65536
Out of bounds: <bc_ushort object at 0xb732d38c> initial value 65536 is not between 0 & 65535

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

<bc_byte object at 0xb732d3d4> 7
107
Out of bounds: <bc_byte object at 0xb732d3d4> update value 137 is not between -128 & 127

关于python - 创建 'generic' 类继承外部模块类的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31317553/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com