Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 类中的可下标对象_Python_Class_Python 3.x_Subscript - Fatal编程技术网

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):
关于
元类的一些要点

  • 当您指定SomeClass作为元类时,将调用SomeClass来创建Dog类

  • Dog类将是元类的
    \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'