-1

I'm coming from a C/C++ world and am having a hard time making all of the OOP analogies in python. I wrapped my script in a class and now get this error in my log() 'private' instance method:

AttributeError: 'instancemethod' object has no attribute 'counter'

def __log(self, contents):                                                  
    sys.stdout.write(contents)                                              

    # Append all writes after the first                                     
    if not hasattr(self.__log, "counter"):                                  
        self.__log.counter = 1                                              
        f = open(self.output_filepath, 'w')                                 
    else :                                                                  
        f = open(self.output_filepath, 'a')                                 

    f.write(contents)                                                       
    f.close()   
tarabyte
  • 17,837
  • 15
  • 76
  • 117
  • 1
    I strongly recommend that you not use "private" names like "__log". They are ugly, and don't actually prevent access. Python works differently that C++. Use it for its own sake. – Ned Batchelder Oct 05 '14 at 18:21
  • They're a very strong "stay off" sign, though. As a co-developer of a major Python library, I can tell you how important it is to use underscores to signal the interface/implementation boundary to users. – Fred Foo Oct 05 '14 at 18:45
  • Fine, use a single underscore. Double underscores just say, "I'm used to Java or C++, and want my private keyword back!" – Ned Batchelder Oct 05 '14 at 23:30

3 Answers3

1

self.__log.counter references to a counter variable which does not exist in the __log method.

if you need the counter variable to be part of the instance of the object, refer to it via self.counter

if you need the counter to be static to the class, define the variable in the class definition outside any methods. check this SO question

if you really really need the counter variable to be part of the instance method, the way to reference it is via ClassName.__log.counter

a good place to start learning OO concepts in python would be the python documentation. https://docs.python.org/2/tutorial/classes.html

Community
  • 1
  • 1
srj
  • 9,591
  • 2
  • 23
  • 27
-1

This you cant add attributes to methods, but you can modify their dict attribute:

class Test:
    def __log(self, contents):                                                  
        sys.stdout.write(contents)                                              

        # Append all writes after the first                                     
        if not "counter" in self.__log.__func__.__dict__:                                  
            self.__log.__func__.__dict__["counter"]= 1                                              
            f = open(self.output_filepath, 'w')  
            print 'w'                               
        else :                                                                  
            f = open(self.output_filepath, 'a') 
            print 'a'                               

        f.write(contents)                                                       
        f.close()  

a = Test()
a._Test__log('') #Prints w
a._Test__log('') #Prints a
b = Test()
b._Test_log('') #Prints a
Piotr Dabkowski
  • 5,661
  • 5
  • 38
  • 47
-1

Python doesn't have static local variables. The best solution to what you want is to use a class attribute:

class WithLog(object):

    opened = False

    def log(self, contents):                                                  
        sys.stdout.write(contents)                                              

        mode = "a" if self.__class__.opened else "w"
        with open(self.output_filepath, mode) as f:
            f.write(contents)       

        self.__class__.opened = True

Of course, it might be better not to constantly open and close the log file....

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662