Python 类中的可下标对象
我有一个名为Python 类中的可下标对象,python,class,python-3.x,subscript,Python,Class,Python 3.x,Subscript,我有一个名为Sparse的python3.4.3类来表示稀疏矩阵和它们之间的运算 除了这个类,我还有一些函数定义,包括如何重载加法运算、打印函数等。但是,当稀疏矩阵表示为字典时,这些函数是编写的,其中键表示非零项的位置,相应的非零项作为值 这些函数在之前的实现中工作得很好,但是当稀疏矩阵作为一个类实现时,这种方法无法产生 TypeError: ` 'Sparse' object is not subscriptable`. 我怎样才能避开这个问题?我附上相关代码以供参考。错误回溯是 Trac
Sparse
的python3.4.3
类来表示稀疏矩阵和它们之间的运算
除了这个类,我还有一些函数定义,包括如何重载加法运算、打印函数等。但是,当稀疏矩阵表示为字典时,这些函数是编写的,其中键表示非零项的位置,相应的非零项作为值
这些函数在之前的实现中工作得很好,但是当稀疏矩阵作为一个类实现时,这种方法无法产生
TypeError: ` 'Sparse' object is not subscriptable`.
我怎样才能避开这个问题?我附上相关代码以供参考。错误回溯是
Traceback (most recent call last):
File "sparse_driver.py", line 11, in <module>
print(s)
File "/mnt/DATA/Dropbox/Courses/Python/HW4/SparseClass.py", line 42, in __str__
sparse_functions.sparse_print(self)
File "/mnt/DATA/Dropbox/Courses/Python/HW4/sparse_functions.py", line 56, in sparse_print
nrow = a['-1'][0]
TypeError: 'Sparse' object is not subscriptable
类别定义
import sparse_functions
class GetAttr(type):
def __getitem__(cls, x):
return getattr(cls, x)
class Sparse:
__metaclass__ = GetAttr
""" Class for sparse matrices"""
# This is the constructor when dimensions and sparsity are specified
def __init__(self, *args):
# The name of the helper function is sparse_gen
if len(args) == 3:
num_row = args[0]
num_col = args[1]
spar = args[2]
if ((type(args[0]) is not int) or (type(args[1]) is not int)):
raise TypeError('The first two arguments should be integers!')
elif not ((args[0] > 0) and (args[1] > 0)):
raise ValueError('The first two agruments should be positive!')
elif not ((args[2] < 1) and (args[2] > 0)):
raise ValueError('Sparsity must be between 0 and 1!')
self.sparse_rep = sparse_functions.sparse_gen(num_row, num_col, spar)
elif len(args) == 1:
if (type(args[0] is not list)):
raise TypeError('The only argument supplied should be a list!')
# The list of lists matrix is provided convert it to sparse
self.sparse_rep = sparse_functions.mat2sparse(arg[0])
else:
raise AttributeError('Invalid number of arguments. There should be either one argument or three arguments!')
# Overload the addition operation
def __add__(a,b):
# Here we can make use of the already defined functions
return sparse_functions.sparse_add(a,b)
# Overload the subtraction operator
def __sub__(a,b):
return sparse_functions.sparse_add(a,-b)
# Overload the print function
def __str__(self):
sparse_functions.sparse_print(self)
…此方法无法生成类型错误“稀疏”对象不是
可订阅的。我怎样才能避开这个问题
通过使用继承:
class GetAttr:
def __getitem__(cls, x):
return getattr(cls, x)
class Sparse(GetAttr):
x = 10
s = Sparse()
print(s['x'])
--output:--
10
顺便说一下,在python3.4
的\uuuuuu元类
行中:
class Dog:
__metaclass__ = SomeClass
什么也不做。我必须写:
class Dog(metaclass=SomeClass):
关于元类的一些要点
:
\uuuu new\uuu()
方法的返回值class MyMetaClass(type):
def stop(self):
print('I will stop.')
def __new__(cls, name, parents, dct):
dct["start"] = lambda self: print('I will start\n.') #See explanation below
return super().__new__(cls, name, parents, dct)
class Dog(metaclass=MyMetaClass):
pass
d = Dog()
d.start()
d.stop()
--output:--
I will start.
Traceback (most recent call last):
File "1.py", line 14, in <module>
d.stop()
AttributeError: 'Dog' object has no attribute 'stop'
一个类的
\uuuu init\uuuuuuuuuuuuuuo()
方法可以用来初始化一个类的实例,类似地,一个元类的\uuuuuuuuuuuuuuo()
方法可以用来初始化一个类。这里的问题是你混淆了元类(类是它们的实例)和超类(类是它们的子类)的用法
元类作用于类,这一事实表明,它们定义的方法(如\uuuuuu getitem\uuuu
)有一个参数,我们通常通过以下方式将其表示为类:\uuuu getitem\uuu(cls,index)
在用户定义类上分配自定义元类时,用户定义类的实例不会使用自定义元类中定义的方法,而是使用它们的类
这与超类不同,我们从超类继承适用于用户定义类实例的方法
在不涉及您试图实现的内容的情况下,我将给出一个小示例来演示这一点(使用Py3.5),我希望您能够理解其中的要点
首先,定义\uuu getitem\uuuu()
的基本元类:
这作用于所有具有\uuuu元类\uuuu=MetaCls
的类,如果我们将基类
定义为使用MetaCls
,我们可以看到这适用于类
,但不适用于这些类的实例:
# metaclass is defined in header:
class Base(metaclass=MetaCls):
pass
# works on classes
Base[0]
Using meta __getitem__ on classes that have my type
base_instance = Base()
# fails on instances
base_instance[0] # TypeError!
为了使订阅也能在实例上工作,我们需要定义适当的超类
,从中我们可以对类中的\uuuu getitem\uuuu>方法进行子类化或重载:
class SuperBase:
def __getitem__(self, index):
print("Using SuperBase __getitem__ on instances that derive from classes that subclass me")
class Base(SuperBase, metaclass=MetaCls):
pass
现在,\uuuuuGetItem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
在类和实例上工作,对于它使用元的类。\uuuuuuuuuuuuuGetItem\uuuuuuuuuuuuuuuuuuuuuuuuuuuu
最后,我不知道为什么你会考虑在这种情况下定义一个自定义元,因为超级类似乎更合适,但我希望你有你的理由
无论采用哪种方法,即使您确实使用重载的\uuuu getitem\uuuu
定义了一个超类,这也会导致另一个错误:
将其余部分保持粘贴状态,只添加一个超类而不是元类:
class MyMetaClass(type):
def __getitem__(cls, x):
return getattr(cls, x)
def __new__(cls, name, parents, dct):
dct["__getitem__"] = cls.__getitem__ #<*****HERE
return super().__new__(cls, name, parents, dct)
class Dog(metaclass=MyMetaClass):
x = 10
d = Dog()
print(d['x'])
--output:--
10
print(d) # Raises the following error:
1 class GetAttr:
2 def __getitem__(self, index):
----> 3 return getattr(self, index)
4 class Sparse(GetAttr):
5 """ Class for sparse matrices"""
AttributeError: 'Sparse' object has no attribute '-1'
这是有道理的print(d)
将导致调用nrow=a['-1'][0]
,它将调用\uuuu getitem\uuuu
,实例为Sparce
和index=-1
\uuuu getitem\uuuu
,当它被编程时,将尝试从类Sparce
中获取名为-1
的属性,这显然是不存在的
我建议在Sparce
类中重载\uuuuu getitem\uuuuuuuuuuuuuuuuuuuuuu
并在\uuuuuu getitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
内对实例中类似数组的对象执行一些。(可能是self.sparse\u rep
?)将所有相关信息放入问题本身;不要使用指向场外资源的链接。a['-1'][0]
您正在使用字符串为矩阵编制索引。
# metaclass is defined in header:
class Base(metaclass=MetaCls):
pass
# works on classes
Base[0]
Using meta __getitem__ on classes that have my type
base_instance = Base()
# fails on instances
base_instance[0] # TypeError!
class SuperBase:
def __getitem__(self, index):
print("Using SuperBase __getitem__ on instances that derive from classes that subclass me")
class Base(SuperBase, metaclass=MetaCls):
pass
Base[0] # meta invocation
Using meta __getitem__ on classes that have my type
base_instance = Base()
base_instance[0] # super invocation
Using SuperBase __getitem__ on instances that derive from classes that subclass me
print(d) # Raises the following error:
1 class GetAttr:
2 def __getitem__(self, index):
----> 3 return getattr(self, index)
4 class Sparse(GetAttr):
5 """ Class for sparse matrices"""
AttributeError: 'Sparse' object has no attribute '-1'