如何在不创建实例的情况下选择性地访问 class 方法

How do I access a class method optionally without creating an instance

我是 python 的新手,对 OOP 很熟悉。我正在制作一个 class 来对数据执行一些基本方法,但理想情况下我想将这些 class 方法作为常规函数访问,而不必先创建实例。

我为 MyMethod 设置了以下代码,其中包含一个方法 'clip_sphere',它将 xyz 坐标作为数组,returns 坐标位于以 [=33= 为中心的球体内] 半径 'radius'

import numpy as np

class MyMethod:

    def __init__(self,xyz):
        self.xyz = xyz

    def clip_sphere(self, center, radius):

        self.xyz = self.xyz - np.array(center).reshape(1,-1)
        r = (np.sum(self.xyz**2, axis = 1))**0.5
        idx = r < radius

        xyz_clip = self.xyz[idx,:]
        self.clip = xyz_clip

        return xyz_clip

我想做的是能够 运行 以两种方式剪辑球体,枯萎 1:

C = MyMethod(xyz)
xyz_clip = C.clip_sphere(center =[0,0,0],radius = 2)

或者简单地将其作为函数调用,例如:

xyz_clip = clip_sphere(xyz,center =[0,0,0],radius = 2)

最好不要重写为普通函数。这可能与某些装饰器有关吗?或者这是否可能。

编辑:看完一些答案后,我想我想问的是如何获得像 numpy reshape 这样的函数。因为这通过允许像这样的语句来工作:

a = np.reshape(np.array([1,2,3]),[3,1]) 

这就像一个函数 以及:

 a = np.array([1,2,3]) 
 a.reshape([3,1])

这就像一个 class 方法

看起来你想要一个独立的函数,而不是 class/object:

def clip_sphere(xyz, center, radius):

    xyz = xyz - np.array(center).reshape(1,-1)
    r = (np.sum(xyz**2, axis = 1))**0.5
    idx = r < radius

    xyz_clip = xyz[idx,:]
    clip = xyz_clip

    return xyz_clip

您可以创建一个名为 clip_sphere():

的全局函数
def clip_sphere(xyz, center, radius):
   return MyMethod(xyz).clip_sphere(center, radius)

但是这样做让我想知道你为什么需要 class。据我所知,您在这里所做的,创建 Sphere class 可能更有意义。这显然是一个具有某些属性的对象:radiuscenter。然后你可以添加一个 clip() 方法来做你想做的事:

class Sphere:
   def __init__(center, radius):
      self.center = center
      self.radius = radius

   def clip(x, y, z):
      # code goes here

回复编辑:

After looking through some of the answers, I guess what I'm asking is how to get a function like numpy reshape. as this works by both allowing a statement like:

a = np.reshape(np.array([1,2,3]),[3,1])

Which is acting like a function As well as:

a = np.array([1,2,3]) 
a.reshape([3,1])

这是两个不同的函数,而不是调用同一个函数的两种不同方式。

它是 sort-of built-in - 您需要做的就是从 class' 命名空间获取函数:

C = MyMethod(xyz)
xyz_clip = MyMethod.clip_sphere(C, center =[0,0,0], radius = 2)

但是,这仍然需要您拥有 class 的实例。问题是编写代码是为了在特定命名对象 中查找 xyz 等属性 ,即名为 self 的对象。 (Python 中的名称 self 没有什么特别之处。)

如果您真的需要能够使用 xyz 来实现此功能,那么明智的做法是编写一个简单的函数来处理它:

# At top level
def clip(xyz, center, radius):
    xyz -= np.array(center).reshape(1,-1)
    r = (np.sum(xyz**2, axis = 1))**0.5
    idx = r < radius
    return xyz[idx,:]

然后为了避免重复代码,可以用这个来实现方法:

# inside the class
def clip_sphere(self, center, radius):
    # This part of the process needs to be repeated, because the
    # `xyz` variable during the `clip` call is a separate name.
    # However, you should consider whether you *actually* want to modify
    # the object's `self.xyz` as a part of this process. My guess is you do not.
    self.xyz -= np.array(center).reshape(1,-1)
    self.clip = clip(self.xyz, center, radius) # uses the top-level `clip`.

牢记描述符的工作原理,您可以对正确编写的 clip_sphere 方法进行小的修改,让您 运行 该方法既可以作为方法,也可以作为 classmethod 接受坐标作为第一个参数:

def clip_sphere(self, center, radius):
    xyz = self.xyz if isinstance(self, __class__) else self
    xyz -= np.array(center).reshape(1,-1)
    r = (np.sum(self.xyz**2, axis = 1))**0.5
    idx = r < radius
    xyz_clip = self.xyz[idx,:]
    if isinstance(self, __class__):
        self.clip = xyz_clip
        self.xyz = xyz
    return xyz_clip

您可以将其作为方法调用:

>>> xyz = ...
>>> MyMethod().clip_sphere(...)

或作为 classmethod:

>>> MyMethod.clip_sphere(xyz, ...)