How do I call a class function inside the class definition?

一笑奈何 提交于 2021-01-28 21:29:53

问题


class MetaData():

    maxSize = 2**10

    # class definition code
    if not os.path.exists('sample.data'):
        SSD  = open('sample.data', 'wb+')
        data = {
            0: [],
            1: {'.': None,}
        }
        data[1]['~'] = data[1]

        MetaData.save()  # i want to call the save function here


    # class function
    @classmethod
    def save(cls):

        cls.SSD.seek(0)
        cls.SSD.write(b' ' * cls.maxSize)
        cls.SSD.seek(0)
        cls.SSD.write(pickle.dumps(cls.data))

I want to use the save() function inside the class block. I've tried MetaDate.save() and simply save() both of which throw errors

Is there any way to achieve this?

Edit

Yes, maxSize is a class var and yes i can access it using cls.maxSize.


回答1:


Your question is very similar to one I asked once — Calling class staticmethod within the class body? — which is interesting because it means you could make it a static method instead and call it like this:

import os
import pickle


class MetaData:
    maxSize = 2**10

    @staticmethod
    def save():
        SSD.seek(0)
        SSD.write(b' ' * cls.maxSize)
        SSD.seek(0)
        SSD.write(pickle.dumps(cls.data))

    # class definition code
    if not os.path.exists('sample.data'):
        SSD  = open('sample.data', 'wb+')
        data = {
            0: [],
            1: {'.': None,}
        }
        data[1]['~'] = data[1]

        save.__func__()  # Call the save function



回答2:


Here's another answer.

You can use a metaclass to workaround to the limitation that you can't reference the class in the class body (since the class doesn't exist yet). You can create the class in the metaclass __new__() method and then modify it — in this case by calling a classmethod defined in it. Here's what I mean:

import os
import pickle


class MetaMetaData(type):
    def __new__(meta, classname, bases, classdict):

        cls = type.__new__(meta, classname, bases, classdict)

        if not os.path.exists('sample.data'):
            cls.SSD = open('sample.data', 'wb+')

            cls.data = data = {
                0: [],
                1: {'.': None,}
            }
            data[1]['~'] = data[1]

            cls.save()

        return cls


class MetaData(metaclass=MetaMetaData):
    maxSize = 2**10

    @classmethod
    def save(cls):
        cls.SSD.seek(0)
        cls.SSD.write(b' ' * cls.maxSize)
        cls.SSD.seek(0)
        cls.SSD.write(pickle.dumps(cls.data))

    # class definition code
    ...


if __name__ == '__main__':
    print(MetaData.data)

Output produced from running it for the first time (i.e. when there was no preexisting sample.data file):

{0: [], 1: {'.': None, '~': {...}}}

Note that the SSD class attribute is an open file — which is very strange, but that's what your code would do too, if it were runnable.




回答3:


At the point when you call save, the class is not yet defined. One way to get around this is to use inheritance and define save in the base-class:

class B:
    @classmethod
    def save(cls):
        print("Saving")

class A(B):
    B.save()

Then of course, variables in the head of A are not known in B.save and have to be given as arguments to save.

Well, or like this:

class B:
    SSD = None

    @classmethod
    def save(cls):
        print(f"Saving {cls.SSD}")

class A(B):
    B.SSD = 3.14

    B.save()


来源:https://stackoverflow.com/questions/65645419/how-do-i-call-a-class-function-inside-the-class-definition

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!