2

Recently I defined one of my Python classes as shown below.

from datetime import datetime, date, time import enums class ExampleClass: defaults = (-1, "", "", datetime.today(), "", -1, [], "", -1, "", "", [], "") def __init__(self, **kwargs): count = 0 for ex in enums.ExampleEnums: setattr(self, ex.name, kwargs.get(ex.value, ExampleClass.defaults[count])) count += 1 def __str__(self): return_string = "Example Object with " count = 0 for val in enums.ExampleEnums: if (getattr(self, val.name) != ExampleClass.defaults[count]): return_string += str("%s: %s, " % (val.name, getattr(self, val.name))) count += 1 return return_string[:-2] def __repr__(self): return_string = "" count = 0 for val in enums.ExampleEnums: if (getattr(self, val.name) != ExampleClass.defaults[count]): return_string += str("%s=%s, " % (val.value, getattr(self, val.name))) count += 1 return return_string[:-2] def __eq__(self, other): for val in enums.ExampleEnums: if (getattr(self, val.name) != getattr(other, val.name)): return False return True def __ne__(self, other): for val in enums.ExampleEnums: if (getattr(self, val.name) == getattr(other, val.name)): return False return True 

Anyway, I'm wondering: is this a good way to write a class definition for a data class? Are there any ways I could improve this? I don't need any code, just generalities are fine as I'm only posting this as a way to see how I can improve my own coding abilities in Python.

Thanks

6
  • I'm glad that my suggestions are well received, but please don't edit the original code in your question (see What you may and may not do after receiving answers). Commented Jun 19, 2015 at 11:37
  • 1
    @mkrieger1 - that meta post is specific to Code Review, and Stack Overflow has different systems in place. Commented Jun 19, 2015 at 11:38
  • @rolfl Oh, I just saw it. But don't the same (or at least similar) principles apply here? Commented Jun 19, 2015 at 11:40
  • Actually, isn't this whole question more suited for Code Review than for Stack Overflow? Commented Jun 19, 2015 at 11:43
  • 1
    It strikes me that this whole question is off-topic because there's no specific programming question.... and, the whole question should have been asked on Code Review, but, be that as it may, no, the same principles do not apply here - though often I think they should. Commented Jun 19, 2015 at 11:44

3 Answers 3

2

You use this pattern several times (shown here is __init__, it applies to __str__ and __repr__ as well):

count = 0 for ex in enums.ExampleEnums: setattr(self, ex.name, kwargs.get(ex.value, ExampleClass.defaults[count])) count += 1 

It would be better to iterate directly over the items in ExampleClass.defaults instead of manually counting an index. This can be achieved using zip:

for ex, default in zip(enums.ExampleEnums, ExampleClass.defaults): setattr(self, ex.name, kwargs.get(ex.value, default)) 

The __eq__ method can be simplified using all:

def __eq__(self, other): return all(getattr(self, val.name) == getattr(other, val.name) for val in enums.ExampleEnums) 

Then, as others have already said, you can express __ne__ in terms of __eq__, or even using the == operator:

def __ne__(self, other): return not self == other 
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. I wasn't aware of zip. Really appreciate it
1

You can call self._eq__(other) in function __ne__.

1 Comment

I like it. And I would've done it but is that Pythonic? Just curious
0

The best way to write a data class will vary on use case. But on what you've presented, you shouldn't repeat code. Once you've defined the __eq__ operator, you should be using that elsewhere. (What if your definition of __eq__ changes?) Also, you don't have to define every magic method under the sun... just the things that are valuable to you.

Check out this guide to Python's magic methods: http://www.rafekettler.com/magicmethods.html

Also see this answer on __ne__ vs __eq__ and how to define them: Python implementing ne operator based on eq.

You should also look into decorators (and @property, specifically).

1 Comment

Thanks for your response. As was mentioned above, the __ne__ operator was changed to reflect its symmetry with the __eq__ operator. Further, I'm not defining them all, just the ones that will probably be useful to me or that I will use often enough that I want to explicitly state their operation. Finally, before this I was using @property but I don't particularly care about them being private, I just didn't like writing out the same sort of definitions over and over again.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.