如何在执行时创建Python方法?

2024-09-27 23:21:23 发布

您现在位置:Python中文网/ 问答频道 /正文

以下代码运行良好,并显示了在执行时创建属性和方法的方法:

class Pessoa:
    pass
p = Pessoa( )
p.nome = 'fulano'

if hasattr(p, 'nome'):
    print(p) 
p.get_name = lambda self:'Sr.{}'.format(self.nome)

但是,我认为我创造方法的方法是不正确的。还有其他方法可以动态创建方法吗?在


Tags: 方法lambdanameselfgetif属性pass
3条回答

[虽然这一点在史蒂芬·伦巴尔斯基的评论中得到了回答,他指出了两个独立的问题,但我在这里添加了一个简短的综合答案。]

是的,你是对的,这并没有正确定义一个方法。在

>>> class C:
...   pass
...
>>> p = C()
>>> p.name = 'nickie'
>>> p.get_name = lambda self: 'Dr. {}'.format(self.name)
>>> p.get_name()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: <lambda>() takes exactly 1 argument (0 given)

下面是如何调用存储在对象p的属性get_name中的函数

^{pr2}$

为了正确地动态定义实例方法,请看一看relevant question的答案。在

如果要动态定义类方法,则必须将其定义为:

>>> C.get_name = lambda self: 'Dr. {}'.format(self.name)

尽管该方法将被添加到现有对象中,但这对p(因为它已经有自己的属性get_name)无效。但是,对于新对象:

^{4}$

而且(显然),对于没有name属性的对象,该方法将失败:

>>> r = C()
>>> r.get_name()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
AttributeError: C instance has no attribute 'name'

在Python3中动态创建方法有两种:

  • 在类本身上创建方法:只需将函数分配给成员;该类的所有对象都可以访问它,即使它们是在创建方法之前创建的:

    >>> class A:          # create a class
        def __init__(self, v):
            self.val = v
    
    
    >>> a = A(1)             # create an instance
    >>> def double(self):    # define a plain function
        self.val *= 2
    
    >>> A.double = double    # makes it a method on the class
    >>> a.double()           # use it...
    >>> a.val
    2
    
  • 在类的实例上创建方法。由于types模块,types在Python 3中是可能的:

    >>> def add(self, x):    # create a plain function
        self.val += x
    
    
    >>> a.add = types.MethodType(add, a)  # make it a method on an instance
    >>> a.add(2)
    >>> a.val
    4
    >>> b = A(1)
    >>> b.add(2)                 # chokes on another instance
    Traceback (most recent call last):
      File "<pyshell#55>", line 1, in <module>
        b.add(2)
    AttributeError: 'A' object has no attribute 'add'
    >>> type(a.add)               # it is a true method on a instance
    <class 'method'>
    >>> type(a.double)
    <class 'method'>
    

方法1(类上)的细微变化可用于创建静态或类方法:

>>> def static_add(a,b):
    return a+b

>>> A.static_add = staticmethod(static_add)
>>> a.static_add(3,4)
7
>>> def show_class(cls):
    return str(cls)

>>> A.show_class = classmethod(show_class)
>>> b.show_class()
"<class '__main__.A'>"

下面是我如何将方法添加到从库导入的类中。如果我修改了库,那么在下一次库升级时将丢失这些更改。我不能创建一个新的派生类,因为我不能告诉库使用我修改过的实例。因此,我通过添加缺少的方法来修补现有类:

# Import the standard classes of the shapely library
import shapely.geometry

# Define a function that returns the points of the outer 
# and the inner polygons of a Polygon
def _coords_ext_int_polygon(self):
    exterior_coords = [self.exterior.coords[:]]
    interior_coords = [interior.coords[:] for interior in self.interiors]
    return exterior_coords, interior_coords

# Define a function that returns the points of the outer 
# and the inner polygons of a MultiPolygon
def _coords_ext_int_multi_polygon(self):
    if self.is_empty:
        return [], []
    exterior_coords = []
    interior_coords = []
    for part in self:
        i, e = part.coords_ext_int()
        exterior_coords += i
        interior_coords += e
    return exterior_coords, interior_coords

# Define a function that saves outer and inner points to a .pt file
def _export_to_pt_file(self, file_name=r'C:\WizardTemp\test.pt'):
    '''create a .pt file in the format that pleases thinkdesign'''
    e, i = self.coords_ext_int()
    with open(file_name, 'w') as f:
        for rings in (e, i):
            for ring in rings:
                for x, y in ring:
                    f.write('{} {} 0\n'.format(x, y))

# Add the functions to the definition of the classes
# by assigning the functions to new class members
shapely.geometry.Polygon.coords_ext_int = _coords_ext_int_polygon
shapely.geometry.Polygon.export_to_pt_file = _export_to_pt_file

shapely.geometry.MultiPolygon.coords_ext_int = _coords_ext_int_multi_polygon
shapely.geometry.MultiPolygon.export_to_pt_file = _export_to_pt_file

请注意,同一个函数定义可以分配给两个不同的类。在

编辑

在我的例子中,我没有向我的类添加方法,而是向我安装的开源库^{}添加方法。在

在您的帖子中,您使用p.get_name = ...向对象实例p添加一个成员。我首先定义一个函数_xxx(),然后用class.xxx = _xxx将其添加到类定义中。在

我不知道你的用例,但通常你会向实例中添加变量,向类定义中添加方法,这就是为什么我要向你展示如何将方法添加到类定义而不是实例中。在

Shapely管理几何对象并提供计算多边形面积的方法,以及相互添加或减去多边形的方法,以及许多其他非常酷的东西。在

我的问题是我需要一些shapely没有提供的现成方法。在

在我的示例中,我创建了自己的方法,该方法返回外部轮廓的点列表和内部轮廓的点列表。我创建了两个方法,一个用于Polygon类,另一个用于MultiPolygon类。在

我还需要一个方法将所有点导出为.pt文件格式。在本例中,我只创建了一个同时处理PolygonMultiPolygon类的方法。在

此代码位于名为shapely_monkeypatch.py的模块中(请参见monkey patch)。当导入模块时,定义名称以_开头的函数,然后将它们分配给名称不带_的现有类。(Python中的惯例是使用_作为仅供内部使用的变量或函数的名称。)

相关问题 更多 >

    热门问题