0

I write a function that gets a filename, reads out information from the file and creates a Read object out of it.

def read_file(filename):   
  with open(filename, 'r') as filetoread:
        readList = []
        for line in filetoread:
            readList.append(Read(line))
        return readList

This implementation works.

Now I want to generalize my function and make it work for two object/class types: Read and Reference. So I want to use a class name as a parameter of a function. The function gets a filename and a classname now. It reads out information from the file and creates an object of a specified classname out of it.

My attempt lookes like this.

def read_file(filename, classname):
  with open(filename, 'r') as filetoread:
        readList = []
        for line in filetoread:
            readList.append(classname(line))
        return readList

I get TypeError: 'str' object is not callable.

My idea was using this solution:

def str_to_class(classname):
    return getattr(sys.modules[__name__], classname)

Source: Convert string to Python class object?

I still get an error though (TypeError: getattr(): attribute name must be string)

Hash_Mag
  • 13
  • 4
  • 2
    No? If you already have `Reference` then why do you need that function at all? – DeepSpace Jan 10 '23 at 18:58
  • It would help to know what you are trying to accomplish. As @DeepSpace said, I don't see what the purpose of this is, if you already have `Reference` – Hutch Jan 10 '23 at 19:01
  • The thing is that I have to implement a function that would create objects out of a file. So the function gets a filename and a name of a class and depending on the user input two different class types could be created. Like this: def read(file, classname). So if classname is "Reference" - Reference object should be created and if the classname is "Read" - Read Object should be created – Hash_Mag Jan 10 '23 at 19:08
  • This is clearly an [xy problem](https://xyproblem.info). You should ask about your actual problem. – DeepSpace Jan 10 '23 at 19:15
  • @DeepSpace, you are right. I have modified my question – Hash_Mag Jan 10 '23 at 19:40
  • @Hutch I tried to explain what I try to accomplish in my question update. Sorry for being not clear. – Hash_Mag Jan 10 '23 at 19:48
  • @DeepSpace Is my question/ problem understandable now? – Hash_Mag Jan 10 '23 at 20:13
  • @Kate_teryna Where is this file coming from? Are you saving the state of your objects to a file? It sounds like you are trying to do some serialization/deserialization. Does that sound accurate? – Hutch Jan 10 '23 at 20:35
  • I added an answer, but without the larger context, it's hard to say what the proper way to handle this would be. I would look into serialization/deserialization. – Hutch Jan 10 '23 at 20:58

2 Answers2

0

The error: TypeError: 'str' object is not callable. is telling you your problem.

For an object to be "callable" it must implement the __callable__() magic method. Strings do not implement this method, and therefore you get this error.

But wait! You know what does implement __callable__()? Classes!

Now rather than trying to do some conversion, just pass in the raw characters. This classname is a token and will be treated as such.

Therefore when calling your function

Use: read_file("myFile.txt", Read)

and NOT: read_file("myFile.txt", "Read")

Hutch
  • 829
  • 7
  • 25
-2

Lets imagine you have a class A

class A:
    pass

If you call str the result should be <class '__main__.A'>:

str(A) == "<class '__main__.A'>"

for get class name you can use __name__ method

str_to_class(Reference.__name__)

or modify your function to str_or_class_to_class ;-)

  • 1
    This is not what OP attempts to do. Anyway, what do *you* imagine to be a useful usage of `str_to_class(Reference.__name__)`? You already have `Reference`, why would you go `str_to_class(Reference.__name__)` -> `str_to_class("Reference")` just to get `Reference` back? – DeepSpace Jan 10 '23 at 19:14
  • I dont know what OP attempts to do. You suggest to return class from `str_to_class` function if it accept classes. I think that is a good idea to rename and modify this function to str_or_class_to_class (my second suggestion). – Kapustin Alexander Jan 10 '23 at 19:22
  • But anyway, maybe for this issue is enough to use `Reference.__name__`, who knows? – Kapustin Alexander Jan 10 '23 at 19:23
  • Which would still make 0 sense, at all. Either way this shouldn't really be an answer. – DeepSpace Jan 10 '23 at 19:23