Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
204 views
in Technique[技术] by (71.8m points)

python - How to access an attribute defined in __init__() in the methods decorated with @classmethod?

I am trying to access cls.dates in both the methods defined in the class decorated with @classmethods. But below code gives me an error Database has no attribute dates. I need help to access it in the methods.

class Database:
""" class that works with data storage and retrieval. """

    def __init__(cls, file='D:\vscode\Python\data.db'):
        # initialise database with a file-name

        cls.dates = {
            1:31,
            2:28,
            3:31,
            4:30,
            5:31,
            6:30,
            7:31,
            8:31,
            9:30,
            10:31,
            11:30,
            12:31
        }

    @classmethod
    def add(cls, data):
        connection = sqlite3.connect('D:\vscode\Python\data.db')
        c = connection.cursor()
        c.execute('INSERT INTO mydata (accuracy, efficiency, day, month) VALUES (?, ?, ?, ?);', (data[0], data[1], data[2], data[3]))
        connection.commit()
        connection.close()

    @classmethod
    def get(cls, date):
        (_day, _month) = tuple(map(int, date.split('-')))

        #calculate low-expressions
        if _day <= 3:
            low_month = _month-1
            low_day = cls.dates[low_month]-(3-_day)
        else:
            low_month = _month
            low_day = _day-3

        #calculate high-expression
        if _day > cls.dates[_month]-3:
            high_month = _month+1
            high_day = _day - cls.dates[_month] + 3
        else:
            high_month = _month
            high_day = _day + 3

        # establish connection and retrive the data
        connection = sqlite3.connect('D:\vscode\Python\data.db')
        c = connection.cursor()
        c.execute('SELECT accuracy, efficiency, day, month FROM mydata WHERE day BETWEEN (?) AND (?) AND month BETWEEN (?) and (?);',(low_day, high_day, low_month, high_month))
        to_plot = c.fetchall()
        connection.close()

        # return the data
        return to_plot

I cannot access the dates attribute of the Database class from any method.

question from:https://stackoverflow.com/questions/66067590/how-to-access-an-attribute-defined-in-init-in-the-methods-decorated-with

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You need to understand the difference between a class and an object. An object is an instance of a class. You can have many objects (instances) of the same class An object has all of the class's data and methods, but also it's own data.

classmethods run on the class. Instance methods run on the object. A classmethod can't access data from an object of the class because (among other reasons) there can be many objects of that class.

You have two options:

  1. Make the classmethods instance methods (delete the @classmethod decorator). Then, they are methods on the object and can access object level data.

  2. Move the data you want to be accessible by the classmethods to the class (put it outside the init function).

Option 1:

class Database:
    def __init__(self):
        self.dates = {...}
    
    def add(self, data):
        logic(self.dates)

database = Database()
database.add(...)

Option 2:

class Database:
    dates = {...}
    
    @classmethod
    def add(cls, data):
        logic(cls.dates)

Database.add(...)

BTW, it is convention to refer to the first parameter of classmethods as cls and the first parameter of instance methods as self to avoid this very confusion.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...