Python class attributes vs meta classes vs class variables - python

I have a mongo wrapper with hooks to a timer class, basically, every time a collection is updated or saved it spawns a timer which in turn executes a given function when it expires. My question is, what would be the pythonic way to specify those functions? My thought was to simply add them to the collection wrapper like this:
class TestCollection(Collection):
__name__ = 'test_collection'
__database__ = 'test'
__primary_key__ = 'field_1'
post_delete = 'call_this_func_with_getattr_after_delete'
expire = 'also_call_this_with_getattr_when_timer_expires'
field_1 = Key()
field_2 = Key()
field_3 = Key()
Then I can just add the logic on my timer class to run the specified function when expired and the same for my mongo wrapper. This could also be achieved in different ways (class Meta, mangled attribute names, etc...) but I just wanted to know the general consensus when doing something like this.

Don't store names you have to look up when you cab just store references to callables directly. Any function, method, or an instance of a class with a __call__ method, is an object just like anything else, and can be stored in your expired attribute.

Related

What an instance attribute will represent in database? for a Django model

Let say i have a model called foo:
class Foo(models.Model):
col_one = models.SomeFiled(...)
col_two = models.SomeFiled(...)
Now i know col_one and col_two will represent columns in the database,but if i add the init() method to the model like so:
class Foo(models.Model):
col_one = models.SomeFiled(...)
col_two = models.SomeFiled(...)
def __init__(self):
attr_one=value_one
Now each instance of Foo will represent a record in the Database,but what attr_one will represent for that particular record,is it like meta data associated with that record? is it going to be stored in the database when the object created for the first time?
I am new to both python and Django if my question is trivial.
In your specific case, attr_one is a local variable just like in any python function that is gone once the function is done executing.
If on the other hand you meant self.attr_one=... then this would be a class instance attribute which would be lost once the object is destroyed. That is, it is only created when that function is called, it is accessible and defined as long as that same instance of the python object is used, but lost of you retrieve the same object from the database from scratch.
All that said, I would not override the __init__ method of a django model. Especially not without calling super(). It will inhibit core django functionality and probably cause errors.

Calling type(dict) functions within classes on class variables (Python 3.4)

I am creating a class and trying to define class variables that correspond to a function like .keys() or .values() that are called on another class variable.
For example:
class DATA(object):
def __init__(self, id, database = {}):
self.id = id
self.database = database
self.addresses = database.keys()
self.data = database.values()
This does not seem to work, as when I create an instance of the class
foo = DATA(0,{"a":1,"b":2})
and then ask for:
print(foo.addresses)
>>> []
and it gives back an empty list.
Note:
On my actual program I start out with an empty dictionary for any class instance, then later on I use a function to add to the dictionary. In this case calling the ".database" still works but ".addresses" does not.
Can anyone help me with this problem?
I'm not sure that this is the problem, but using a mutable such as {} as a default argument often leads to bugs. See: "Least Astonishment" and the Mutable Default Argument
This is safer:
def __init__(self, id, database=None):
if database is None:
self.database = {}
else:
self.database = database
I don't understand the purpose of DATA.addresses and DATA.data. Could you use functions with the property decorator instead, to avoid redundancy?
#property:
def addresses(self):
return self.database.keys()
#property:
def data(self):
return self.database.values()
The issue is that you're calling keys right in your __init__ method, and saving the result. What you want to do instead is to call keys only when you want to access it.
Now, depending on the requirements of your class, you may be able to do this in a few different ways.
If you don't mind exposing changing the calling code quite a bit, you could make it very simple, just use foo.database.keys() rather than foo.addresses. The latter doesn't need to exist, since all the information it contains is already available via the methods of the databases attribute.
Another approach is to save the bound instance method database.keys to an instance variable of your DATA object (without calling it):
class DATA(object)
def __init__(self, database=None):
if database is None:
database = {}
self.database = database
self.addresses = database.keys # don't call keys here!
In the calling code, instead of foo.addresses you'd use foo.addresses() (a function call, rather than just an attribute lookup). This looks like a method call on the DATA instance, though it isn't really. It's calling the already bound method on the database dictionary. This might break if other code might replace the database dictionary completely (rather than just mutating it in place).
A final approach is to use a property to request the keys from the database dict when a user tries to access the addresses attribute of a DATA instance:
class DATA(object)
def __init__(self, database=None):
if database is None:
database = {}
self.database = database
# don't save anything as "addresses" here
#property
def addresses(self):
return self.database.keys()
This may be best, since it lets the calling code treat addresses just like an attribute. It will also work properly if you completely replace the database object in some other code (e.g. foo.database = {"foo":"bar"}). It may be a bit slower though, since there'll be an extra function call that the other approaches don't need.

Is it possible in Python to make a set of methods of a class dependent on input of constructor?

I am reading this Genshi Tutorial and see there the following example:
from formencode import Schema, validators
class LinkForm(Schema):
username = validators.UnicodeString(not_empty=True)
url = validators.URL(not_empty=True, add_http=True, check_exists=False)
title = validators.UnicodeString(not_empty=True)
As far as I understand this example, we create a new class that inherits Schema class and this class contain three methods: username, url, title. However, I am not sure about the last because before I only saw methods created with def.
Anyway, my question is not about that. I would like to know if it is possible to make the definition of the class dynamic. For example, sometimes I do not want url or title to be in the class. It seems to be doable (I just use if and assign a value to url only if-statement is satisfied.
But what if I do not know in advance what fields I would like to have in the form? For example, now I have username, url and title. But what if later I would like to have city or age. Can I do something like that:
from formencode import Schema, validators
class LinkForm(Schema):
__init__(self, fields):
for field in fields:
condition = fields[field]
field = validators.UnicodeString(condition)
I think it will not work. Is there a work around in this case?
Yes, you can add methods to an instance dynamically. No, you can't do what you want.
You can bind methods to the instance in the initializer. Unfortunately what you have there are descriptors and those must be bound to the class.
I would go the other way round—first define all form fields that might be used, and delete unneeded ones later.
Provided that you have:
from formencode import Schema, validators
class LinkForm(Schema):
username = validators.UnicodeString(not_empty=True)
url = validators.URL(not_empty=True, add_http=True, check_exists=False)
title = validators.UnicodeString(not_empty=True)
you could do either this:
def xy():
my_form = LinkForm()
del my_form.url
…
… or this:
def xy():
class CustomLinkForm(LinkForm):
pass
if …:
del CustomLinkForm.url
…
Disclaimer: I am not familiar with FormEncode, so it might depend on its inner workings which of these two versions actually works.
of course you can have a constructor with some arguments after self and these arguments will be the value for some members of your class if you have for instance
__init__(self, fields):
self.fields = []
for field in fields:
self.fields = self.fields + field
see this in Dive into Python
class FileInfo(UserDict):
"store file metadata"
def __init__(self, filename=None):
UserDict.__init__(self)
self["name"] = filename
Classes can (and should) have doc strings too, just like modules and
functions.
init is called immediately after an instance of the
class is created. It would be tempting but incorrect to call this the
constructor of the class. It's tempting, because it looks like a
constructor (by convention, init is the first method defined for
the class), acts like one (it's the first piece of code executed in a
newly created instance of the class), and even sounds like one (“init”
certainly suggests a constructor-ish nature). Incorrect, because the
object has already been constructed by the time init is called,
and you already have a valid reference to the new instance of the
class. But init is the closest thing you're going to get to a
constructor in Python, and it fills much the same role.
The first
argument of every class method, including init, is always a
reference to the current instance of the class. By convention, this
argument is always named self. In the init method, self refers to
the newly created object; in other class methods, it refers to the
instance whose method was called. Although you need to specify self
explicitly when defining the method, you do not specify it when
calling the method; Python will add it for you automatically.
init methods can take any number of arguments, and just like
functions, the arguments can be defined with default values, making
them optional to the caller. In this case, filename has a default
value of None, which is the Python null value.
Note that in the later example you learn how to deal with inherited class, calling __init()__ for this inherited class.
To answer your not-a-question about class or instance variables, see this
Variables defined in the class definition are class variables; they
are shared by all instances. To create instance variables, they can be
set in a method with self.name = value. Both class and instance
variables are accessible through the notation “self.name”, and an
instance variable hides a class variable with the same name when
accessed in this way. Class variables can be used as defaults for
instance variables, but using mutable values there can lead to
unexpected results. For new-style classes, descriptors can be used to
create instance variables with different implementation details.

Python descriptors (__get__, __set__) on function parameters

Normally a descriptor is used on a class attribute like so:
class Owner(object):
attr = Attr()
When getting Owner.attr, Attr.__get__(self, instance, owner) is called where self = Owner.attr, instance = None and owner = Owner.
When Owner is instantiated instance will be the instance of Owner.
Now I would like to apply this concept to method parameters instead of class attributes.
How it would look in practice (let's assume that the functionality of Attr is to wrap a string with a given string):
class Example(object):
def funct(self, param=Attr('t')):
return param == 'test' # < param calls the descriptor here
e = Example()
e.funct('es') # < is True because 'es' wrapped with 't' becomes 'test'.
When accessing param, Attr.__get__(self, instance, owner) will be called with self = funct.param, instance = funct and owner = funct (although it doesn't make sense to have owner and instance the same, might be None?).
But since funct is not a class, this will not work. How can I get something similar to work?
A decorator on the function will be processing the parameters, so this might add to the solution I think.
The decorator must be, for example, be able to change the wrapper string.
Functions actually are first class objects in Python, but you are correct in saying that the syntax you describe would not work as you want. You could potentially do something like this with a decorator that inspects the passed attributes for characteristics that would enable this sort of functionality though. However, you'd probably be better off implementing a callable object, then attaching descriptors to that and creating instances of the callable rather than functions.

Python weird class variables usage

Suppose we have the following code:
class A:
var = 0
a = A()
I do understand that a.var and A.var are different variables, and I think I understand why this thing happens. I thought it was just a side effect of python's data model, since why would someone want to modify a class variable in an instance?
However, today I came across a strange example of such a usage: it is in google app engine db.Model reference. Google app engine datastore assumes we inherit db.Model class and introduce keys as class variables:
class Story(db.Model):
title = db.StringProperty()
body = db.TextProperty()
created = db.DateTimeProperty(auto_now_add=True)
s = Story(title="The Three Little Pigs")
I don't understand why do they expect me to do like that? Why not introduce a constructor and use only instance variables?
The db.Model class is a 'Model' style class in classic Model View Controller design pattern.
Each of the assignments in there are actually setting up columns in the database, while also giving an easy to use interface for you to program with. This is why
title="The Three Little Pigs"
will update the object as well as the column in the database.
There is a constructor (no doubt in db.Model) that handles this pass-off logic, and it will take a keyword args list and digest it to create this relational model.
This is why the variables are setup the way they are, so that relation is maintained.
Edit: Let me describe that better. A normal class just sets up the blue print for an object. It has instance variables and class variables. Because of the inheritence to db.Model, this is actually doing a third thing: Setting up column definitions in a database. In order to do this third task it is making EXTENSIVE behinds the scenes changes to things like attribute setting and getting. Pretty much once you inherit from db.Model you aren't really a class anymore, but a DB template. Long story short, this is a VERY specific edge case of the use of a class
If all variables are declared as instance variables then the classes using Story class as superclass will inherit nothing from it.
From the Model and Property docs, it looks like Model has overridden __getattr__ and __setattr__ methods so that, in effect, "Story.title = ..." does not actually set the instance attribute; instead it sets the value stored with the instance's Property.
If you ask for story.__dict__['title'], what does it give you?
I do understand that a.var and A.var are different variables
First off: as of now, no, they aren't.
In Python, everything you declare inside the class block belongs to the class. You can look up attributes of the class via the instance, if the instance doesn't already have something with that name. When you assign to an attribute of an instance, the instance now has that attribute, regardless of whether it had one before. (__init__, in this regard, is just another function; it's called automatically by Python's machinery, but it simply adds attributes to an object, it doesn't magically specify some kind of template for the contents of all instances of the class - there's the magic __slots__ class attribute for that, but it still doesn't do quite what you might expect.)
But right now, a has no .var of its own, so a.var refers to A.var. And you can modify a class attribute via an instance - but note modify, not replace. This requires, of course, that the original value of the attribute is something modifiable - a list qualifies, a str doesn't.
Your GAE example, though, is something totally different. The class Story has attributes which specifically are "properties", which can do assorted magic when you "assign to" them. This works by using the class' __getattr__, __setattr__ etc. methods to change the behaviour of the assignment syntax.
The other answers have it mostly right, but miss one critical thing.
If you define a class like this:
class Foo(object):
a = 5
and an instance:
myinstance = Foo()
Then Foo.a and myinstance.a are the very same variable. Changing one will change the other, and if you create multiple instances of Foo, the .a property on each will be the same variable. This is because of the way Python resolves attribute access: First it looks in the object's dict, and if it doesn't find it there, it looks in the class's dict, and so forth.
That also helps explain why assignments don't work the way you'd expect given the shared nature of the variable:
>>> bar = Foo()
>>> baz = Foo()
>>> Foo.a = 6
>>> bar.a = 7
>>> bar.a
7
>>> baz.a
6
What happened here is that when we assigned to Foo.a, it modified the variable that all instance of Foo normally resolve when you ask for instance.a. But when we assigned to bar.a, Python created a new variable on that instance called a, which now masks the class variable - from now on, that particular instance will always see its own local value.
If you wanted each instance of your class to have a separate variable initialized to 5, the normal way to do it would be like this:
class Foo(object);
def __init__(self):
self.a = 5
That is, you define a class with a constructor that sets the a variable on the new instance to 5.
Finally, what App Engine is doing is an entirely different kind of black magic called descriptors. In short, Python allows objects to define special __get__ and __set__ methods. When an instance of a class that defines these special methods is attached to a class, and you create an instance of that class, attempts to access the attribute will, instead of setting or returning the instance or class variable, they call the special __get__ and __set__ methods. A much more comprehensive introduction to descriptors can be found here, but here's a simple demo:
class MultiplyDescriptor(object):
def __init__(self, multiplicand, initial=0):
self.multiplicand = multiplicand
self.value = initial
def __get__(self, obj, objtype):
if obj is None:
return self
return self.multiplicand * self.value
def __set__(self, obj, value):
self.value = value
Now you can do something like this:
class Foo(object):
a = MultiplyDescriptor(2)
bar = Foo()
bar.a = 10
print bar.a # Prints 20!
Descriptors are the secret sauce behind a surprising amount of the Python language. For instance, property is implemented using descriptors, as are methods, static and class methods, and a bunch of other stuff.
These class variables are metadata to Google App Engine generate their models.
FYI, in your example, a.var == A.var.
>>> class A:
... var = 0
...
... a = A()
... A.var = 3
... a.var == A.var
1: True

Categories

Resources