简体   繁体   中英

Is there a way to call a method on a Python object returned by a function?

So I'm building a command-line tutorial program of sorts in Python. Basically it emulates a terminal and walks you through different levels using shell commands. The way the original version worked is I caught anything entered and analyzed it for calls to the tutorial program if there weren't any I passed the command to the computer using os.system().

Unfortunately, since I wrote the tutorial to be of a *nix system, it does not work on Windows, since I included levels using vim and what-not. My plan was to rewrite the program, but rather than making calls to the system, I'd create a virtual filesystem. This includes to objects: directory and file. You can probably figure out what both of the objects are meant to be. The directory object would contain a list of its contents and this would act as the filesystem. I would then implement commands like cd, ls, pwd, and so-on.

The problem I have run in to is that when I return a containing directory or file from a directory object I'm not able to edit it in any way. I'll give you an example of my code.

NOTE: There are likely bugs in the code as I cannot test it very well without fixing this issue Also, the imports aren't necessary to the problems. The first one is a color class that lays out the codes for doing colored output and the second is a file that contains global variables. I've removed the calls to these resources so that it will run on someone else's system

#from ..resources.colors import colors
#from ..resources import variables as var

class Directory:
    # Basic constructor
    def __init__(self, name="", container=None, contents=[]):
        self.name = name
        self.container = container
        self.contents = contents
    
    # grabs index of contents by name
    def index(self, find):
        for i in range(len(self.contents)):
            if self.contents[i].name == find:
                return i
        return -1
    
    # Add something to the container
    def add(self, dirFile):
        # Check for duplicate names
        if self.index(dirFile.name) != -1:
            return False

        self.contents.append(dirFile)
        return True

    # Retrieve something that's in contents
    def get(self, neededName):
        ind = self.index(neededName)
        if ind >= 0:
            return self.contents[ind]

    # Returns true if it has at least one sub directory
    def has_sub(self):
        for content in self.contents:
            if type(content) == Directory:
                return True
        return False
    
    # Iterates through, looks for slashes and goes to subs (recursion, ooooh!)
    def get_sub(self, path=""):
        if not self.has_sub() or path == "":
            return self
        
        pathSplit = path.split("/")
        nextDir = self.index(pathSplit[0])
        
        if nextDir >= 0:
            return self.contents[nextDir]
        
        pathSplit.pop(0)
        path = "/".join(pathSplit)
        return self.get_sub(path)


        
            

    # ============== Shell Commands ==============

    # List all contents in directory
    def ls(self):
        for content in self.contents:
            if type(content) == Directory:
                #print(colors.fg.blue + content.name + colors.reset + "\t", end="") This is the code wih the colors class
                print(content.name + "\t", end="")
            else:
                print(content.name + "\t", end="")
        print()

    # Delete file by name:
    def rm(self, toDelete):
        ind = self.index(toDelete)
        if ind >= 0:
            self.contents.pop(ind)
            return True
        else:
            return False
    
    # Make new dir
    def mkdir(self, name=""):
        if name:
            self.add(Directory(name))
            
        
## Current test
di = Directory("Test")
di.mkdir("one")
di.mkdir("two")

di.get_sub("one").mkdir("test")

di.ls()
di.get_sub("one").ls()

The current output is:

one  two  test
one  two  test

But the output should read:

one two
test

For some reason when I call:

di.get_sub("one").mkdir("test")

It changes di rather than the object returned by get_sub()

Any help is much appreaciated. Let me know if there's anything else I should provide.

There are a couple of pointers I think I can give you. The first is, probably most appropriately, to answer your primary question:

It changes di rather than the object returned by get_sub()

This is likely because no matter how things work out, has_sub() will eventually resolve to a subdirectory with no further directories in. This will result in this clause becoming true:

        if not self.has_sub() or path == "":
            return self

if not self.has_sub will evaluate true and return di . It'll always be di as your recursive routine always calls methods on self which is di . I hope that makes sense!

In terms of the second pointer I can give you, maybe I can ask a couple of questions regarding your test-case which might assist with some discover and though processes:

1: di = Directory("Test")
2: di.mkdir("one")
3: di.mkdir("two")

4: di.get_sub("one").mkdir("test")

5: di.ls()
6: di.get_sub("one").ls()
  1. In line one you create Test , then add in (2) and (3) new (I suppose) subdirectories. However, looking at mkdir in your Directory implementation, these don't actually get created. Perhaps look at os.mkdir and consider whether you need to worry about existing directories. os.path.join might also be your friend here...

  2. Have a good look at what you're returning. If you return self you're returning the reference to the object you called the method on. If you chain a second method call to that (in your case) it will still be di that you call it on.

I think you'll have a lot of fun implementing this if you first start looking first looking into os.path as a module then consider some of the additional os functions like mkdir mentioned above. Also consider that os.getcwd() and os.chdir() might be of interest.

I really hope this helps. :-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM