0

I am working with a class which does some math and stores the result, and then a line that sets a "noresult" to that class but initiated with zeroes, like so (I'm leaving out the math, this should be all the relevant bits):

class Result(object):
  def __init__(self, slope, offset):
    self._slope = slope
    self._offset = offset
  
  @classmethod
  def dothemath(cls, etc):
    ...


Result.NORESULT = Result((0, 0), (0, 0))

Then there's a lot of places where it sets an object's "result" attribute to an instance of this class and later says things like "if object.result is not Result.NORESULT"

This works fine, but PyCharm highlights it everywhere it's used by importing the class, complaining that the class has no attribute NORESULT. Is there any way to get the exact same functionality into the definition of the class itself (i.e., calling the class while not needing to initialize it?)

I had two ideas, but neither works:

class Result(object):
  NORESULT = cls((0,0), (0,0))
  
  def __init__:
    ...


class Result(object):
  def __init__(self, slope, offset):
    self.NORESULT = cls((0, 0), (0, 0))
    ...

both give me "Unresolved reference cls", so I guess that doesn't work - and anyway, the second one would require me to initialize the class to get NORESULT instead. I've definitely seen cls() used before in this code so I'm not sure why it works in some places and not others. Is this kind of recursiveness actually something that can be put in the class?

I'm aware Python 2.7 is no longer supported, although it's not part of the snippet of code this particular question is about, I am working with Gwyddion which has no plans to update its Python integration package, gwy, from 2.7 to 3.x.

3
  • cls only works where that name is in scope, as it is in a method where it's the name of the first parameter. It's not a global, or anything magical, just a convention for class method parameter naming.
    – jonrsharpe
    Commented Jan 9 at 18:06
  • @jonsharpe how and why did you just edit my post what the hell. I don't really appreciate that, just tell me what I should change instead of changing my wording...
    – Réka
    Commented Jan 9 at 18:07
  • stackoverflow.com/help/editing
    – jonrsharpe
    Commented Jan 9 at 18:09

1 Answer 1

0

Declare the class attribute with a default value, then re-assign it later.

class Result(object):
  NORESULT = None

  def __init__(self, slope, offset):
    self._slope = slope
    self._offset = offset
  
  @classmethod
  def dothemath(cls, etc):
    ...


Result.NORESULT = Result((0, 0), (0, 0))
9
  • And this wouldn't make it None if I import the class somewhere else? Since I don't know how it deals with importing other code in the same file as the target class, which would like... take precedence, something in the class itself or in the same file but not the class that's being imported
    – Réka
    Commented Jan 9 at 18:03
  • Also the question is less "how do I get it to stop highlighting" and more "is this even possible to NOT do outside the class"
    – Réka
    Commented Jan 9 at 18:03
  • When you import the file, it executes everything in it. So it will do the assignment.
    – Barmar
    Commented Jan 9 at 18:05
  • 1
    I don't think there's a way to do it inside the class definition. The class doesn't exist until the class definition is finished, you can't refer to it yet.
    – Barmar
    Commented Jan 9 at 18:06
  • I see, thank you! I didn't know that about importing executing everything in the file, I was never quite sure exactly how that worked. I guess that's another reason it's good to not just have a bunch of naked code outside a function or a class, which I used to do a lot... not anymore though.
    – Réka
    Commented Jan 9 at 18:12

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.