python 类函数与方法?

0h4hbjxa  于 2023-01-29  发布在  Python
关注(0)|答案(3)|浏览(108)

我正在YouTube here上观看学习Python -初学者完整课程[教程]
在时间戳4:11:54,导师解释了什么是 * 类函数 *,但是根据我使用其他语言进行面向对象编程的背景,我认为正确的术语应该是 * 方法 *?
现在我很好奇 * 类函数 * 和 * 方法 * 之间是否有区别?

mum43rcc

mum43rcc1#

他们错了。但是,这是他们犯的一个小错误,而且做视频课程,包括说话和打字,肯定是有挑战性的。没什么大不了的。
当函数属于一个类时,它是一个方法(一种更特殊的函数形式);当它在类之外时,它是一个函数
我怎么知道他们错了?
在Python中可以使用以下语法创建一个:

class SomeClass:

   @classmethod
   def the_method(cls, vars):
       ....

   def instance_method(self, vars):
       ...

这不是@classfunction装饰器,这是@classmethod装饰器。
请参阅www.example.com上的文档https://docs.python.org/3/library/functions.html#classmethod

g6ll5ycj

g6ll5ycj2#

方法是类中函数的正确术语。方法和函数非常相似。唯一的区别是方法是用对象调用的,并且可以修改对象的数据。函数可以修改和返回数据,但它们对对象没有影响。
编辑:类函数和方法的意思是一样的,尽管说类函数不是正确的表达方式。

myss37ts

myss37ts3#

你不需要用类方法创建一个示例。格式化程序.format(“foo”)vs格式化程序().format(“foo”)。
这也意味着你不能在示例上存储状态/配置,因为没有示例。继承和多态性也可能不适用于类方法--也就是说,如果我打算在类方法上使用它们,我会对实际行为非常谨慎。
在实践中,你通常希望使用常规方法,* 除了创建示例的类方法 *(通常被称为 * 工厂方法 *)。如果你真的不需要示例,也许一个独立的函数也可以完成这项工作。Python不要求函数只存在于类上(像Java)。
至于术语,除了考试的考虑之外,不要担心它。方法和函数没有什么不同,除了一个有一个示例(或@classmethod中的类)作为第一个参数。
通常,如果它缩进在class XXX:声明下,我就调用一个方法,如果它是独立的,我就调用一个函数。

好的,如果你不介意有点困惑,请继续阅读......

除此之外,所有这些东西之间的区别在实践中是相当不稳定的。类方法可以从示例调用,函数可以动态地添加到类中...
这里有一些有趣的东西,大部分是好奇心,除了create_me classmethod,它是使用classmethod作为工厂的主要原因,但是它显示了边界是不固定的。
这不是您通常想要做的事情,但它确实介绍了类上的方法/函数如何行为的一些细微区别。

class Anc:
    @classmethod
    def format(cls, msg):
        "I dont need an instance to work"
        print(f"\n{cls}.format({msg.upper()})") 
        
    def __init__(self, keep=1) -> None:
        self.keep = keep

    def format_instance(self, msg):
        "I do and it allows me to use configuration stored in it"
        print(f"\n{self}.format_instance({msg[:self.keep]=})")

    @classmethod
    def create_me(cls, *args, **kwargs):
        """ a factory is the main reason for class methods """
        return cls(*args, **kwargs)

class Child1(Anc):
    @classmethod
    def format(cls, msg):
        print(f"\n{cls}.format({msg.lower()})") 

    @staticmethod
    def format_static(msg):
        print(f"\nLonely static without cls or instance 😭{msg}😭")

class Child2(Anc):
    def format_instance(self, msg):
        "replace with stars"
        print(f"\n{self}.format_instance({'*' * len(msg)})")

def wannabe_method(self, msg):
    "is this a function or a method?"
    print(f"\nwannabe_method({self},{msg=}).")

def wont_work_as_method():
    "too many arguments when called as method"
    print(f"\nwont_work_as_method()")

Anc.format("calling format as a classmethod.  No instance needed!")

anc = Anc(keep=2)

anc.format("calling format through an instance.  It'll automatically get the class as first argument!")

Child1.format("calling Child1's format, which does lower")

Child2.format("calling Child2's format, which will up on Anc.format")

Child1.format_static("this is a static")

child1 = Child1(keep=3)

child1.format_instance("this message will get truncated...")

child2 = Child2()

try:
    child2.added_method("hey just got added!")
except (AttributeError,) as e: 
    print(f"\n❌as expected this fails {e} cuz missing method")

Child2.added_method = wannabe_method

child2.added_method("hey just got added! self gets the instance magically")

try:
    wannabe_method("nope not gonna work")
except (TypeError,) as e: 
    print(f"\n❌as expected this fails {e} because it only got 1 argument")

wannabe_method("FAKE INSTANCE!", "hackish work")


Child2.wont_work = wont_work_as_method

try:
    child2.wont_work()
except (TypeError,) as e: 
    print(f"\n❌ oh no! no place for self {e}")

child2_through_factory = Child2.create_me()

child2_through_factory.format_instance("My God, it's full of stars")
child2_through_factory.format("to uppercase")

child1_through_factory = Child1.create_me()
child1_through_factory.format("TO LOWERCASE")

输出:

<class '__main__.Anc'>.format(CALLING FORMAT AS A CLASSMETHOD.  NO INSTANCE NEEDED!)

<class '__main__.Anc'>.format(CALLING FORMAT THROUGH AN INSTANCE.  IT'LL AUTOMATICALLY GET THE CLASS AS FIRST ARGUMENT!)

<class '__main__.Child1'>.format(calling child1's format, which does lower)

<class '__main__.Child2'>.format(CALLING CHILD2'S FORMAT, WHICH WILL UP ON ANC.FORMAT)

Lonely static without cls or instance 😭this is a static😭

<__main__.Child1 object at 0x10a824460>.format_instance(msg[:self.keep]='thi')

❌as expected this fails 'Child2' object has no attribute 'added_method' cuz missing method

wannabe_method(<__main__.Child2 object at 0x10a824280>,msg='hey just got added! self gets the instance magically').

❌as expected this fails wannabe_method() missing 1 required positional argument: 'msg' because it only got 1 argument

wannabe_method(FAKE INSTANCE!,msg='hackish work').

❌ oh no! no place for self wont_work_as_method() takes 0 positional arguments but 1 was given

<__main__.Child2 object at 0x10a824220>.format_instance(**************************)

<class '__main__.Child2'>.format(TO UPPERCASE)

<class '__main__.Child1'>.format(to lowercase)

相关问题