1

Please Note: This is a small, similar example of something I'm trying to do for a school assignment and therefore certain pieces of the solution cannot be altered. Those pieces are pointed out.

It is my understanding that str can be used to format how a class is represented when printed.

I am intending to overwrite the str method so that:

>>>print(class_slim)
my name is... Slim Shady

and

>>>print(class_fat)
my name is... Fat Shady

Here is the example code:

class MyClass:
    fname = ''
    lname = ''

    def __init__(self, fname='', lname=''):
        self.name = ""

    def __str__(self):
        return 'my name is... '+self.fname, self.lname

    @staticmethod
    def setname(first, last):
        return first, last


class_slim = MyClass.setname("Slim", "Shady")
print(class_slim)

class_fat = MyClass.setname("Fat", "Shady")
print(class_fat)

Right now, I am getting this result:

>>>class_slim = MyClass.setname("Slim", "Shady")
>>>print(class_slim)
('Slim', 'Shady')

I am required to:

  • use static method (setname) to change fname and lname,
  • different instances of class would need to return different strings (I want to output "my name is... Slim Shady" and "my name is... Fat Shady"...

If any pieces of this are impossible or assumptions I've made are downright wrong please let me know, that may be the issue.

Peter Wood
  • 23,859
  • 5
  • 60
  • 99
cmckeeth
  • 95
  • 2
  • 9
  • 1
    Instead `self.fname, self.lname` do: `self.fname+' '+self.lname`. Otherwise you're returning two strings – Taku Mar 27 '17 at 22:25
  • Why are you using a `staticmethod`? especially if it is suppose to be a setter (an unpythonic thing to begin with...). Very strange... – juanpa.arrivillaga Mar 27 '17 at 22:25
  • Also, I'd be wary of a text-book or tutorial requiring you to use a `staticmethod`, something which has pretty much proved worthless in Python (although, some people like to use them for organizing code). In fact, in this case, I'm pretty sure it isn't possible to modify `fname` and `lname` with a static-method, since you don't have access to the instance or the class. Sounds like maybe a `classmethod` would be more appropriate, although, this should likely just be a plain-old method. – juanpa.arrivillaga Mar 27 '17 at 22:28
  • Why are `fname` and `lname` class attributes? That means different instances of the class will access the *same values*. They really sound like they should be normal, instance attributes. Are you coming from a language like Java, by any chance? – juanpa.arrivillaga Mar 27 '17 at 22:30
  • 2
    But `setname` isn't changing anything, it just returns a `tuple` of the passed in parameters. – Peter Wood Mar 27 '17 at 22:33
  • Also see [Overwrite or override](http://stackoverflow.com/questions/8651562/overwrite-or-override) (hint: it's override) – Peter Wood Mar 27 '17 at 22:36
  • @juanpa.arrivillaga - I'm using staticmethod because that is specified as part of the assignment, although it seems to me that staticmethod defeats the purpose of having instances of a class. – cmckeeth Mar 27 '17 at 23:22
  • Where are you getting this assignment? It sound like someone is teaching Java instead of Python. – juanpa.arrivillaga Mar 27 '17 at 23:25
  • @PeterWood - I may have done it wrong, but I intended setname() to be a method into which you could pass strings as parameters which would change the class attributes, fname and lname. – cmckeeth Mar 27 '17 at 23:25
  • 1
    How would simply returning those values accomplish that? You could do `MyClass.lname = last; MyClass.fname = first` but that would be a pretty silly staticmethod. Of course, silly staticmethods are pretty much par for the course in python... Of course, note, you are changing *class level attributes here* which would make these changes visible to all instances of `MyClass`. – juanpa.arrivillaga Mar 27 '17 at 23:26
  • Wow, ok I see what you're saying about setname() not doing anything sorry noob mistake I'll edit... – cmckeeth Mar 27 '17 at 23:28
  • 2
    Yeah, but more important point: why are `lname` and `fname` *class level attributes*? Shouldn't they be *instance attributes*? Are you sure you aren't reading a Java/C++ textbook?. `self.name` is an instance attribute, on the other hand, but you never do anything with it and it's always going to be and empty string... – juanpa.arrivillaga Mar 27 '17 at 23:34

2 Answers2

0

Ok here's what I ended up doing, the static method needed to new up an instance of a class and return that instance to the parent class built in function, str.

class MyClass:

    def __init__(self, first, last):
        self.fname = first
        self.lname = last

    def __str__(self):
        return 'my name is...'+self.fname+" "+self.lname

    if __name__ == '__main__':
        @staticmethod
        def read(first, last):
            newClass = MyClass(first,last)
            return newClass

class_slim = MyClass.read("Slim", "Shady")
print(class_slim)

class_fat = MyClass.read("Fat","Shady")
print(class_fat)

the output of this is

"my name is...Slim Shady"

"my name is... Fat Shady"

cmckeeth
  • 95
  • 2
  • 9
  • 1
    Okay, again, why the `staticmethod`? You could just replace `MyClass.read("Slim", "Shady")` here with `MyClass("Slim", "Shady")`, since all `MyClass.read` does is call the constructor anyway. What's the point? A static method is effectively a namespaced function that has no intrinsic tie to either the class or the instances of it (if it did, it would be a class method or an instance method). I'm not seeing why `setname` or `read` or whatever should be static, and you haven't explained what the goal of making it static is. – ShadowRanger Mar 28 '17 at 00:29
  • I feel it necessary to point out that this code will only work if the .py file is called as a script, it will throw an exception otherwise. – JacaByte Mar 28 '17 at 01:20
  • @ShadowRanger thanks for your input I agree that staticmethod is not a useful solution, I am using staticmethod because it is specifically required in the assignment. Isn't school fun? – cmckeeth Mar 28 '17 at 15:56
0

You're shooting yourself in the foot by using a staticmethod, without the static method you can set your class instance's attributes without having to reinitialize a new instance of your class. (This operation can be expensive depending on what your class does.)

Without any changes you can change the instance's attributes without a setter method;

slim_ins = MyClass("Slim", "Jim")
print(slim_ins)
# My name is... SlimJim
slim_ins.lname = "Shady"
print(slim_ins)
# My name is... SlimShady

But this will only work with the slim_ins instance of MyClass. This will effect all instances of MyClass, since fname and lname are class attributes! The difference between instances and the classes they are (sub)instances of is subtle but within is the key to OOP in Python; interactions with the attributes and methods of an instance will only effect the instance, while interactions with the attributes and methods of a class will effect all instances of that class and any of its subclasses.

I believe what you need is a class factory, the arguments to a class factory can be used to produce a unique class;

def my_class_factory(first_name, last_name):
    class MyClass(object):
        fname = first_name[:]
        lname = last_name[:]

        def __str__(self):
            return "My name is... "+fname+" "+lname

A static method never comes into play here. You could implement a class factory in a static method and call it from the class object (not to be confused with one of its instances) but you don't need to carry a class factory around with each of your instances, and you shouldn't be instantiating an object from a method other than __init__, because that's what __init__ does.

JacaByte
  • 325
  • 2
  • 8