Bottom Page

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 iundefined is really defined
#1
in the latest testing iteration of this code, at line 83 i am trying to return a reference to a function named close which is defined in line 63. yet i get the message that it is not defined. what can cause this?

here is the output:
Output:
lt2a/phil /home/phil 296> py trytopen.py --------------------------------------------------- start0 CALLING open(*['foo0_6224721824273931', 'w'],**{} CALLED __getattribute__ FOR ('write',) CALLED __getattribute__ FOR ('write',) CALLED __getattribute__ FOR ('close',) Traceback (most recent call last): File "trytopen.py", line 9, in <module> f.close() File "/home/phil/topen.py", line 83, in __getattribute__ return close NameError: name 'close' is not defined lt2a/phil /home/phil 297>
and here is the latest class code:

topen.py:
# -*- coding: utf-8 -*-
import io,os,sys,time

_ofile = []

def _sep():
    return '_'+str(int(time.time()*3906250))

class topen():
    """Class for opening a file with temporary output name and automatic rename on close if write."""
    # name is require by positional args or by keyword args
    # this class is like ztopen but without compression

    def __init__(self,*args,**kwargs):

        if args:
            args = list(args)
            fname = args.pop(0)
            if args:
                modes = args.pop(0)
            else:
                modes = kwargs.pop('mode',None) 
        else:
            fname = kwargs.pop('file',None)
            modes = kwargs.pop('mode',None)

        if fname is None:
            raise('file is missing')
        if modes is None:
            raise('mode is missing')

        if 'x' in modes and isinstance(fname,(str,bytes)) and os.path.exists(fname):
            raise TypeError(f'{fname!r} refers to a name that already exists')

        fname = os.fspath(fname)
        if isinstance(fname,bytes):
            fname = ''.join(chr(x)for x in fname)
        if isinstance(modes,bytes):
            modes = ''.join(chr(x)for x in modes)

        if ('x' in modes or 'w' in modes) and isinstance(fname,str):
            rname = 1
            oname = fname+_sep()
        else:
            rname = 0
            oname = fname

        args = [oname,modes]+list(args)

        print(f'CALLING open(*{args!r},**{kwargs!r}',file=sys.stderr,flush=1)
        ofile = open(*args,**kwargs)
        if ofile is None:
            raise(f'failed to open file {oname!r}')
        _ofile[:0] = [ofile]

        self.rname = rname
        self.ofile = ofile
        self.oname = oname
        self.fname = fname

        self.closed = False

    def close(self):
        if self.rname:
            print(f'close {self.oname!r}',file=sys.stderr,flush=1)
            self.ofile.close()
            print(f'set closed flag True',file=sys.stderr,flush=1)
            self.closed = True
            print(f'rename {self.oname!r} to {self.fname!r}',file=sys.stderr,flush=1)
            return os.rename(self.oname,self.fname)
        else:
            print(f'close {self.oname!r}',file=sys.stderr,flush=1)
            self.closed = True
            return self.ofile.close()

    def __getattr__(self,*args):
        print(f'CALLED __getattr__ FOR {args!r}',file=sys.stderr,flush=1)
        return getattr(_ofile[0],*args)

    def __getattribute__(self,*args):
        print(f'CALLED __getattribute__ FOR {args!r}',file=sys.stderr,flush=1)
        if args[0] == 'close':
            return close
        return getattr(_ofile[0],*args)
any ideas?
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Quote
#2
close is defined in the class dictionary but is not directly reachable from the method.

Try
import types

return types.MethodType(type(self).close, self)
Quote
#3
that seemed to work. it goes further before the next error for something else. i want to understand what this does. the type(self).close part is not understood. does type(self) take any attribute? what does it get when that attribute is used?
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Quote
#4
type() returns the class of the object.

As close is a class method, type(self).close returns that method.

As an example, we can get the upper() method from the str class this way.

x = "foo"          # x is str
cl = type(x)       # cl is the the class of x, an "str"
print(f"The class of x is {cl}")
method = cl.upper  # A method of the class.
print(f"Using the method on a different string we get {method('bar')}")
Output:
The class of x is <class 'str'> Using the method on a different string we get BAR
Quote
#5
what i need to do is get a reference to the method and return it. would it not be good enough in this case to just do return type(self).close?
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Quote
#6
Skaperen Wrote:would it not be good enough in this case to just do return type(self).close?
Assuming that you want the following interface
x = topen('foo')
x.close()
then x.close needs to remember both the instance x and the function object close. That's where bound instance methods come in play. They contain basically an instance and a function and when they are called, they insert the instance as the first argument of the function. The call to types.MethodType() creates the instance method.

If you return only type(self).close, that is to say topen.close in our case, this value does not remember the instance self. You would need to call x.close(x) or get a missing argument error.

Using type(self) instead of topen allows self to be an instance of a subclass of topen if someone ever defines one. This subclass could potentially overwrite the close method.
Skaperen likes this post
Quote

Top Page

Possibly Related Threads...
Thread Author Replies Views Last Post
  python library not defined in user defined function johnEmScott 2 176 May-30-2020, 04:14 AM
Last Post: DT2000

Forum Jump:


Users browsing this thread: 1 Guest(s)