Passing the *class* as function argument - python

I've never done this before, and it seems hacky, but I've tested and it does work. Is this considered OK form:
from audio.models import audio
from document.models import pdf
def count_object_by_sha1(object_type, sha1):
return object_type.objects.filter(sha1=sha1).count()
pdf_count = count_object_by_sha1(pdf, 'somesha1valuehere')
audio_count = count_object_by_sha1(audio, 'somesha1valuehere')
So basically, I'm passing the class to the function and using it to make a query on one or another django objects. Feels like a hack...but it works and makes my code rather simple.
After running into the mutable object in function call issue, I'm a bit skittish about doing weird things with function arguments.

That isn't what you're doing though. You're passing a class, not a module. pdf is evidently a Django model class, since it has an objects attribute.
Either way is fine, though. Classes and modules are first class objects and it's perfectly OK to pass them around, use them in functions, etc.

Related

What is the interpreter looking for?

I never realized just how poor a programmer I was until I came across this exercise below. I am to write a Python file that allows all of the tests below to pass without error.
I believe the file I write needs to be a class, but I have absolutely no idea what should be in my class. I know what the question is asking, but not how to make classes or to respond to the calls to the class with the appropriate object(s).
Please review the exercise code below, and then see my questions at the end.
File with tests:
import unittest
from allergies import Allergies
class AllergiesTests(unittest.TestCase):
def test_ignore_non_allergen_score_parts(self):
self.assertEqual(['eggs'], Allergies(257).list)
if __name__ == '__main__':
unittest.main()
1) I don't understand the "list" method at the end of this assertion. Is it the the Built-In Python function "list()," or is it an attribute that I need to define in my "Allergies" class?
2) What type of object is "Allergies(257).list"
self.assertEqual(['eggs'], Allergies(257).list)
3) Do I approach this by defining something like the following?
def list(self):
list_of_allergens = ['eggs','pollen','cat hair', 'shellfish']
return list_of_allergens[0]
1) I don't understand the "list" method at the end of this assertion. Is it the the Built-In Python function "list()," or is it an attribute that I need to define in my "Allergies" class?
From the ., you can tell that it's an attribute that you need to define on your Allergies class—or, rather, on each of its instances.*
2) What type of object is "Allergies(257).list"
Well, what is it supposed to compare equal to? ['eggs'] is a list of strings (well, of string). So, unless you're going to create a custom type that likes to compare equal to lists, you need a list.
3) Do I approach this by defining something like the following?
def list(self):
list_of_allergens = ['eggs','pollen','cat hair', 'shellfish']
return ist_of_allergens
No. You're on the wrong track right off the bat. This will make Allergies(257).list into a method. Even if that method returns a list when it's called, the test driver isn't calling it. It has to be a list. (Also, more obviously, ['eggs','pollen','cat hair', 'shellfish'] is not going to compare equal to ['eggs'], and ist_of_allergens isn't the same thing as list_of_allergens.)
So, where is that list going to come from? Well, your class is going to need to assign something to self.list somewhere. And, since the only code from your class that's getting called is your constructor (__new__) and initializer (__init__), that "somewhere" is pretty limited. And you probably haven't learned about __new__ yet, which means you have a choice of one place, which makes it pretty simple.
* Technically, you could use a class attribute here, but that seems less likely to be what they're looking for. For that matter, Allergies doesn't even have to be a class; it could be a function that just defines a new type on the fly, constructs it, and adds list to its dict. But both PEP 8 naming standards and "don't make things more complex for no good reason" both point to wanting a class here.
From how it's used, list is an attribute of the object returned by Allergies, which may be a function that returns an object or simply the call to construct an object of type Allergies. In this last case, the whole thing can be easily implemented as:
class Allergies:
def __init__(self, n):
# probably you should do something more
# interesting with n
if n==257:
self.list=['eggs']
This looks like one of the exercises from exercism.io.
I have completed the exercise, so I know what's involved.
'list' is supposed to be a class attribute of the class Allergies, and is itself an object of type list. At least that's one straight-forward way of dealing with it. I defined it in the __init__ method of the class. In my opinion, it's confusing that they called it 'list', as this clashes with Pythons list type.
snippet from my answer:
class Allergies(object):
allergens = ["eggs", "peanuts",
"shellfish", "strawberries",
"tomatoes", "chocolate",
"pollen","cats"]
def __init__(self, score):
# score_breakdown returns a list
self.list = self.score_breakdown(score) # let the name of this function be a little clue ;)
If I were you I would go and do some Python tutorials. I would start with basics, even if it feels like you are covering ground you already travelled. It's absolutely worth knowing your basics/fundamentals as solidly as possible. For this, I could recommend Udacity or codeacademy.

Retrieving argument values from an object instance

If I have an instance of class A, is there anyway to know what arguments were used to instantiate that instance?
I looked up the inspect module, and there are tools that a sooo close, but not quite right. For instance, the inspect.getargvalues(frame) almost works, except you can only get the frame from within the class itself. I want to get these after-the-fact.
Ideally, what I want is:
instance_a = ClassA(arguments)
inspect.get_values_set_to_the_init(instance_a)
I don't want to have to save the arguments from within the init statement if avoidable.
I should say the reason I want this in case there is a completely different approach: I want to be able to recreate a 'replica' of the object by saving the arguments (using my imaginary function above), then instantiating a new object by passing in exactly the same arguments to init. Pickle, Shelve and Marshall don't work since my object is apparently unserializable.

Python argument passing in object oriented programming

I apologize if this was asked somewhere else, but I do not know how else to formulate this question.
I am a physicist and Python is my first object-oriented language. I love this language for its clean code, and somehow everything works as intended (by me ;).
However I have one problem, maybe it is more of a design choice, but since my object oriented programming is self-taught and very basic I am not sure which way to go.
So the question is: should I mainly pass arguments or manipulate the object data directly? Because, for instance:
class test(object):
...
def dosomething(self, x, y):
# do someting with x, y involving a lot of mathematic manipulations
def calcit(self):
k = self.dosomething(self.x[i], self.y[i])
# do something else with k
produces much cleaner code than not passing x, y but passing i and writing the self explicitly every time. What do you prefer, or is this an object oriented paradigm that I am breaking?
Performance-wise this shouldn't make a difference since the arguments are passed by reference, right?
should i mainly pass arguments or manipulate the object data directly
Think of objects as systems with a state. If data belongs to the state of the object, then it should be packaged in the object as a member. Otherwise, it should be passed to its methods as an argument.
In your example, what you should do depends on whether you want to dosomething on values x and y that are not members of the object. If you don't, then you can have dosomething fetch x and y from self.
Also, keep in mind that if you're not using self inside a method, then it probably shouldn't be a method at all but rather a freestanding function.
performance-wise this shouldn't make a difference since the arguments are passed by reference, right?
I wouldn't worry about performance at this point at all.
Object paradigm is that :
you pack up methods and attributes together and call them an object.
So, if you manipulate precisely one of those attributes you don't need to pass them as parameters, you SHOULD use the object's ones. If you use anything else then you got to pass it as parameters.
And nothing prevents you from getting the values of your object into another variable if it bothers you to write self every time !
To finish, your function that takes x and y as parameters should not be in your object but outside of it as an helper function if you really wanna do something like that, the reason being that there is no reason to pass your object as first parameter (even if it's implicit) if you do not use it.
and yeah performance wise it should be pretty similar !

Is it common/good practice to test for type values in Python?

Is it common in Python to keep testing for type values when working in a OOP fashion?
class Foo():
def __init__(self,barObject):
self.bar = setBarObject(barObject)
def setBarObject(barObject);
if (isInstance(barObject,Bar):
self.bar = barObject
else:
# throw exception, log, etc.
class Bar():
pass
Or I can use a more loose approach, like:
class Foo():
def __init__(self,barObject):
self.bar = barObject
class Bar():
pass
Nope, in fact it's overwhelmingly common not to test for type values, as in your second approach. The idea is that a client of your code (i.e. some other programmer who uses your class) should be able to pass any kind of object that has all the appropriate methods or properties. If it doesn't happen to be an instance of some particular class, that's fine; your code never needs to know the difference. This is called duck typing, because of the adage "If it quacks like a duck and flies like a duck, it might as well be a duck" (well, that's not the actual adage but I got the gist of it I think)
One place you'll see this a lot is in the standard library, with any functions that handle file input or output. Instead of requiring an actual file object, they'll take anything that implements the read() or readline() method (depending on the function), or write() for writing. In fact you'll often see this in the documentation, e.g. with tokenize.generate_tokens, which I just happened to be looking at earlier today:
The generate_tokens() generator requires one argument, readline, which must be a callable object which provides the same interface as the readline() method of built-in file objects (see section File Objects). Each call to the function should return one line of input as a string.
This allows you to use a StringIO object (like an in-memory file), or something wackier like a dialog box, in place of a real file.
In your own code, just access whatever properties of an object you need, and if it's the wrong kind of object, one of the properties you need won't be there and it'll throw an exception.
I think that it's good practice to check input for type. It's reasonable to assume that if you asked a user to give one data type they might give you another, so you should code to defend against this.
However, it seems like a waste of time (both writing and running the program) to check the type of input that the program generates independent of input. As in a strongly-typed language, checking type isn't important to defend against programmer error.
So basically, check input but nothing else so that code can run smoothly and users don't have to wonder why they got an exception rather than a result.
If your alternative to the type check is an else containing exception handling, then you should really consider duck typing one tier up, supporting as many objects with the methods you require from the input, and working inside a try.
You can then except (and except as specifically as possible) that.
The final result wouldn't be unlike what you have there, but a lot more versatile and Pythonic.
Everything else that needed to be said about the actual question, whether it's common/good practice or not, I think has been answered excellently by David's.
I agree with some of the above answers, in that I generally never check for type from one function to another.
However, as someone else mentioned, anything accepted from a user should be checked, and for things like this I use regular expressions. The nice thing about using regular expressions to validate user input is that not only can you verify that the data is in the correct format, but you can parse the input into a more convenient form, like a string into a dictionary.

Python: how to make a function visible throughout a program

I have two functions like the following:
def fitnesscompare(x, y):
if x.fitness>y.fitness:
return 1
elif x.fitness==y.fitness:
return 0
else: #x.fitness<y.fitness
return -1
that are used with 'sort' to sort on different attributes of class instances.
These are used from within other functions and methods in the program.
Can I make them visible everywhere rather than having to pass them to each object in which they are used?
Thanks
The best approach (to get the visibility you ask about) is to put this def statement in a module (say fit.py), import fit from any other module that needs access to items defined in this one, and use fit.fitnesscompare in any of those modules as needed.
What you ask, and what you really need, may actually be different...:
as I explained in another post earlier today, custom comparison functions are not the best way to customize sorting in Python (which is why in Python 3 they're not even allowed any more): rather, a custom key-extraction function will serve you much better (future-proof, more general, faster). I.e., instead of calling, say
somelist.sort(cmp=fit.fitnesscompare)
call
somelist.sort(key=fit.fitnessextract)
where
def fitnessextract(x):
return x.fitness
or, for really blazing speed,
import operator
somelist.sort(key=operator.attrgetter('fitness'))
Defining a function with def makes that function available within whatever scope you've defined it in. At module level, using def will make that function available to any other function inside that module.
Can you perhaps post an example of what is not working for you? The code you've posted appears to be unrelated to your actual problem.

Categories