从实例调用类方法作为方法是一种不好的形式吗?

发布于 2024-07-15 17:51:11 字数 363 浏览 2 评论 0原文

前任。

如果我有这样的东西:

class C(object):
    @classmethod
    def f(cls, x):
       return x + x

这会起作用:

c = C()

c.f(2)
4

但这是不好的形式吗? 我应该只调用

C.f()

or

c.__class__.f()

显然,这只有在 f 不与 self/cls 交互并期望它是类的情况下才有意义。

Ex.

If I have something like this:

class C(object):
    @classmethod
    def f(cls, x):
       return x + x

This will work:

c = C()

c.f(2)
4

But is that bad form?
Should I only call

C.f()

or

c.__class__.f()

Obviously, this would only make sense in cases where f doesn't interact with self/cls expecting it to be class.

?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

酒中人 2024-07-22 17:51:11

如果您想从实例调用类方法,您可能不需要类方法。

在示例中,由于您最后的评论(没有 self/cls 交互),您给出的静态方法将更合适。

class C(object):
    @staticmethod
    def f(x):
       return x + x

是“良好的形式”

c = C()
c.f(2)

这样,两者兼而有之

C.f(2)

If you are tempted to call a class method from an instance you probably don't need a class method.

In the example you gave a static method would be more appropriate precisely because of your last remark (no self/cls interaction).

class C(object):
    @staticmethod
    def f(x):
       return x + x

this way it's "good form" to do both

c = C()
c.f(2)

and

C.f(2)
心舞飞扬 2024-07-22 17:51:11

我不记得在类外部使用过这样的类方法,但是实例方法本身调用类方法当然是可以的(例如 self.foo() where foo< /code> 是一个类方法)。 这可以确保继承按预期运行,并将在正确的子类而不是基类中调用 .foo()

I don't recall using a classmethod like this from outside the class, but it is certainly ok for an instance method to call a classmethod on itself (e.g. self.foo() where foo is a classmethod). This makes sure that inheritance acts as expected, and will call .foo() in the right subclass instead of the base class.

煮茶煮酒煮时光 2024-07-22 17:51:11

主要是看起来很混乱。 如果我在使用你的课程并看到这个,它会让我想知道里面还有什么其他惊喜,它看起来像是糟糕的设计。

它不仅仅是静态方法有什么原因吗?

It's mainly just confusing looking. If I were using your class and saw this, it would make me wonder what other surprises are in there, it just looks like bad design.

Is there a reason it's not just a staticmethod?

温折酒 2024-07-22 17:51:11

Cf()c_instance.f() 更清晰,而 c_instance.__class__.f() 则很丑陋。 由于清晰和美观是 python 社区深受喜爱的特性,因此我倾向于说 Cf() 是最好的路线。

您是否有任何特殊原因想要以其他方式调用它?

C.f() is clearer than c_instance.f(), and c_instance.__class__.f() is just ugly. Since clarity and beauty are dearly loved characteristics in the python community, I'd tend to say that C.f() is the best route.

Is there any particular reason you even want to call it in either of the other ways?

椵侞 2024-07-22 17:51:11

我在从非类方法调用一些类方法(需要是类方法,以便我仍然可以引用该类)时遇到了这个问题,如下所示。

class A:
  def a(self, number):
    print("a", self, number)
    self.b(number)

  @classmethod
  def b(cls, number):
    print("b", cls, number + 1)
    cls.c(number)

  @classmethod
  def c(cls, number):
    print("c", cls, number * 2)



b = A()
b.a(3) 

上面的代码产生以下结果:

a <__main__.A object at 0x000001FAC09FE358> 3
b <class '__main__.A'> 4
c <class '__main__.A'> 6

我并不是说这是最好的约定,但它不会破坏 Python 3.6 中的任何内容

I came across this where I was calling some classmethods (that need to be classmethods so that I still have reference to the class) from a non-classmethod, like the following.

class A:
  def a(self, number):
    print("a", self, number)
    self.b(number)

  @classmethod
  def b(cls, number):
    print("b", cls, number + 1)
    cls.c(number)

  @classmethod
  def c(cls, number):
    print("c", cls, number * 2)



b = A()
b.a(3) 

The above code produces the following result:

a <__main__.A object at 0x000001FAC09FE358> 3
b <class '__main__.A'> 4
c <class '__main__.A'> 6

I'm not saying that it's the best convention, but it doesn't break anything in Python 3.6

不再见 2024-07-22 17:51:11

如果您已经有一个 C 实例,为什么需要 f() 作为类方法? 这不仅是不好的形式,而且通常没有必要。 网上有人说:“这很糟糕,因为它给人的印象是对象中的某些实例变量被使用了,但事实并非如此。”

不过,学习的第 484 页python 指出,您可以以任何一种方式调用该方法,只要传入相同的实例,它就会完全相同。

If you have an instance of C already, why do you need f() to be a class method? Not only is it bad form, its usually not necessary. Someone on the net says: "This is bad because it creates the impression that some instance variables in the object are used, but this isn't the case."

Although, page 484 of learning python notes that you can call the method either way and it will be exactly the same as long as you pass the same instance in.

缘字诀 2024-07-22 17:51:11

我认为问题在于风格,也就是说,如果你想要一个类方法,你应该将其称为类方法MyClass.my_func(),还是作为实例方法myinst.my_func()。 记录@classmethod<的解释/code> 装饰器的优点是它允许您像调用实例方法一样调用类方法。 我在下面提供了一个示例来说明这一点。

至于风格,我认为无论如何都不应该让人们感到困惑,它实际上是方法实现细节。 如果您在实例的上下文中调用类方法(即作为类实例对象的用户,或在类实例方法内部),那么将类方法作为另一个实例方法调用是完全可以的,甚至可能更愿意不这样做突出显示有关被调用方法的一些实现细节。

我该怎么办? 如果我将实例属性传递给类方法,我可能会在 MyClass.my_func(self.some_value) 中调用类方法,而不是调用 self.my_func(self.some_value) 因为看到后者让我想知道为什么 my_func 不读取 self.some_value 本身,而不是让我传递它。 否则我真的不介意任何一种形式。

当然,类是用来实例化的,最大的错误是程序员将它们用作无状态方法的某种命名空间。

class A:
    value = 2

    def __init__(self, value):
        self.value = value
    
    def add_instance(self, number):
        self.value += number


    @classmethod
    def add_class(cls, number):
        cls.value += number


    def add_class_via_instance(self, number):
        self.add_class(number)

    def add_class_via_class(self, number):
        A.add_class(number)

    def add_class_via_sneak(self, number):
        self.__class__.value += number



a = A(1)
print(f'{A.value=} {a.value=}')
a.add_instance(3)
print(f'{A.value=} {a.value=}')
A.add_class(3)
print(f'{A.value=} {a.value=}')
a.add_class_via_class(3)
print(f'{A.value=} {a.value=}')
a.add_class_via_instance(3)
print(f'{A.value=} {a.value=}')
a.add_class_via_sneak(3)
print(f'{A.value=} {a.value=}')

回报

A.value=2 a.value=1 # expect class and instance have different value values
A.value=2 a.value=4 # adding to the instance
A.value=5 a.value=4 # adding to the class
A.value=8 a.value=4 # calling the function as a class method works on the class attribute
A.value=11 a.value=4 # calling the function as a instance method works on the class attribute as well
A.value=14 a.value=4 # instance methods can access class values and therefore can behave as a classmethod if they want.

I think the question is that of style, which is to say, if you want a class method, should you call it as a class method MyClass.my_func(), or as an instance method myinst.my_func(). On of the of documented explinations of the @classmethod decorator is that it will allow you to call the class method as if it was an instance method. I have included an example showing this below.

As for style, I think it should not be confusing to people either way, it really is the method implementation detail. If you are calling the class method in the context of an instance (i.e. as a user of a class instance object , or inside class instance methods), then calling class method as just another instance method is perfectly okay, and maybe even preferred to not highlighting some implementation detail about the method being called.

What would I do? If I was passing an instance attribute into a classmethod, I'd probably call the classmethod in the MyClass.my_func(self.some_value), rather then calling self.my_func(self.some_value) because seeing the latter makes me wonder why my_func isn't reading self.some_value itself, instead of making me pass it along. Otherwise I really don't mind either form.

Of course, classes are meant to be instantiated, and the biggest faux pas is programmers using them as some sort of namespace for stateless methods.

class A:
    value = 2

    def __init__(self, value):
        self.value = value
    
    def add_instance(self, number):
        self.value += number


    @classmethod
    def add_class(cls, number):
        cls.value += number


    def add_class_via_instance(self, number):
        self.add_class(number)

    def add_class_via_class(self, number):
        A.add_class(number)

    def add_class_via_sneak(self, number):
        self.__class__.value += number



a = A(1)
print(f'{A.value=} {a.value=}')
a.add_instance(3)
print(f'{A.value=} {a.value=}')
A.add_class(3)
print(f'{A.value=} {a.value=}')
a.add_class_via_class(3)
print(f'{A.value=} {a.value=}')
a.add_class_via_instance(3)
print(f'{A.value=} {a.value=}')
a.add_class_via_sneak(3)
print(f'{A.value=} {a.value=}')

returns

A.value=2 a.value=1 # expect class and instance have different value values
A.value=2 a.value=4 # adding to the instance
A.value=5 a.value=4 # adding to the class
A.value=8 a.value=4 # calling the function as a class method works on the class attribute
A.value=11 a.value=4 # calling the function as a instance method works on the class attribute as well
A.value=14 a.value=4 # instance methods can access class values and therefore can behave as a classmethod if they want.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文