Python Function that creates class instances - python

Hello i want to create a function which creates instances of a class
def make_instance(name_instance)
name_instance=puppy()
class puppy:
def __init__(self,name):
self.name =name
make_instance(cloud)
# when i pass an argument it says the variable is undefined and i use #isinstance() it return False.

Your puppy class needs to take a name value into its constructor, and you're currently not passing in anything.
Also your function doesn't return the instance at all. It simply re-assigns the instance to the variable name_instance that you pass in (losing your input). The return value of make_instance right now is None
My guess is that you want your implementation to look like the following
def make_instance(name_instance)
return puppy(name_instance)
I do want to point out though that this function isn't useful unless it does more than just create the instance, you're just adding wrapper code around the constructor

Related

Python how to get self from class function?

Can I get self from class function? For example:
class abc:
def __init__(self, name):
self.name = name
def printname(self):
print(self.name)
x = abc("test").printname()
I want to get original class obj abc("test") from x without using return self or define x = abc("test") at first, is it possible?
The short answer is no.
The longer answer:
printname is not a "class function", it's an instance method. A class method is one that takes the class as the first parameter. Most methods are instance methods; they take self (a particular instance of the class) as the first parameter. If this were indeed a class method, there would be no "self" associated with it.
The thing you're referring to as a "class object" is an instance of the class abc. abc is itself an object (everything in Python is an object, including class definitions), but that's not the same thing as the instance you get by calling abc("test").
Any time you want to take a value that's local to a particular function call and make it available to the caller (including its parameters), you need to return it. There are technically other tricks involving mutating state in the caller's scope, but those aren't applicable to your example. If you ended printname with the line return self, then doing x = abc("test").printname() would result in the instance being assigned to x.
In your example, the caller is the one that constructs the instance, so simply writing this would also do the trick:
x = abc("test")
x.printname()

When to use self and when not to use self

Which class option is preferable and why?
Option 1
class Person():
def __init__(self):
pass
def sayHello(self, name):
print "{} says hello!".format(name)
def driver(self):
for name in names: # names is generated in the driver function by some means of input
self.sayHello(name)
Option 2
class Person():
def __init__(self):
self.name = None
def sayHello(self):
print "{} says hello!".format(self.name)
def driver(self):
for name in names: # names is generated in the driver function by some means of input
self.name = name
self.sayHello()
You can assume that there are more variables than just name and that multiple functions are using these variables. The main point I am trying to make is that the variable value's are changing inside the for loop
Even though your exemple is syntaxically correct, it doesn't help at all understand your question regarding how to use a instance attribute.
From want I'm guessing, there's two questions :
When to use a class method (def foo(self, bar)) ?
When to use a instance attribute (self.name) ?
Instance attribute should be used when you need to "share" a variable between functions or retrieve it from outside a function. That variable will be "attached" to the object (for exemple, the color of a car, the nickname of a user, ...)
If your function / method need to call this kind of variable, it must use self to get it, so you have to set it as the first argument when defining this function.
If you just need a temporary variable to loop over it and do some stuff, you don't need to use a class method, a simple function will do the trick.

Constructing from a classmethod

Suppose I am creating a class representing and object in a KV-datastore. Creating the constructor is pretty straightforward...
class KVObject:
def __init__(self, key, value, add=True):
self.key = key
self.value = value
if add == True:
kv_create(key, value)
Now, let's say I want to retrieve a KV-object... and construct a class instance from it. I figure I'll add this class method onto my DataBaseObject class.
#classmethod
def get_kv_object(cls, key):
value = kv_get(key)
cls.__init__(key, value, add=False)
... but when calling init from the class method (cls.__init__), Python asks for an argument for self!
Any ideas? Many thanks! I know this is a bit of a simple example, but it definitely applies to some more complex, interesting situations!
Edit: Thanks for the responses. I learned something helpful while researching this, which is that object.__new__ calls __init__ on an object when calling MyClass(...), effectively providing an uninitialized instance of the class to MyClass.init with the args called from within MyClass. Likewise, it makes sense to call cls(...), as suggested in your answers. Thank you.
Think about how you would create a new database object normally, it would be something like the following:
instance = DatabaseObject(key, value, add=False)
Well within your class method the first parameter (cls in this case) is just another name for DatabaseObject, so to create an instance you would do the following:
instance = cls(key, value, add=False)
#classmethod
def get_kv_object(cls, key):
value = kv_get(key)
return cls(key, value, add=False)
__init__ does not created new instances of the cls class! It's a method that's called right after the object has been created.

Can't make properties work within nested methods

Im trying to create a class with some formatting options. But i can't figure out how to do it properly...
The code produced the following error:
AttributeError: 'NoneType' object has no attribute 'valuesonly'
class Testings(object):
def format_as_values_only(self,somedata):
buildstring=somedata.values()
return buildstring
def format_as_keys_only(self):
pass
def format_as_numbers(self):
pass
def get_data_method(self):
self.data= {'2_testkey':'2_testvalue',"2_testkey2":"2_testvalue2"}
#property
def valuesonly(self):
return format_as_values_only(self.data)
test=Testings()
print test.get_data_method().valuesonly
The important thing for me is to be able to get the formatters like: class.method.formatter or so...
Thanks a lot for any hints!
get_data_method has no return value, so the result of test.get_data_method() is None. That's why you're getting that exception.
If you really want to do something like test.get_data_method().valuesonly, either define the valuesonly property on Testings, and have get_data_method return self, or have get_data_method return some new object with the properties that you want defined.
You can't do things this way. Methods are just functions defined directly inside a class block. Your function is inside another function, so it's not a method. The property decorator is useless except in a class block.
But, more fundamentally, function definitions just create local names, the same as variable assignments or anything else. Your valuesonly function is not accessible at all from outside the get_data_method function, because nothing from within a function is accessible except its return value. What you have done is no different than:
def get_data_method(self):
a = 2
. . . and then expecting to be able to access the local variable a from outside the function. It won't work. When you call get_data_method(), you get the value None, because get_data_method doesn't return anything. Anything you subsequently do with the result of get_data_method() is just operating on that same None value.
If you want to access things using the syntax you describe, you will need to make get_data_method return an object that has properties like valuesonly. In other words, write another class that provides a valuesonly property, and have get_data_method return an instance of that class. A rough outline (untested):
class DataMethodGetter(object):
def __init__(self, parent):
self.parent = parent
#property
def valuesonly(self):
return format_as_values_only(self.parent.data)
class Testings(object):
# rest of class def here
def get_data_method(self):
self.data = {'blah': 'blah'}
return DataMethodGetter(self)
However, you should think about why you want to do this. It's likely to be simpler to set it up to just call valuesonly directly on the Testing object, or to pass a flag to get_data_method, doing something like get_data_method(valuesonly=True).

Why does "self" outside a function's parameters give a "not defined" error?

Look at this code:
class MyClass():
# Why does this give me "NameError: name 'self' is not defined":
mySelf = self
# But this does not?
def myFunction(self):
mySelf2 = self
Basically I want a way for a class to refer to itself without needing to name itself specifically, hence I want self to work for the class, not just methods/functions. How can I achieve this?
EDIT: The point of this is that I'm trying to refer to the class name from inside the class itself with something like self.class._name_ so that the class name isn't hardcoded anywhere in the class's code, and thus it's easier to re-use the code.
EDIT 2: From what I've learned from the answers below, what I'm trying to do is impossible. I'll have to find a different way. Mission abandoned.
EDIT 3: Here is specifically what I'm trying to do:
class simpleObject(object):
def __init__(self, request):
self.request = request
#view_defaults(renderer='string')
class Test(simpleObject):
# this line throws an error because of self
myClassName = self.__class__.__name__
#view_config(route_name=myClassName)
def activateTheView(self):
db = self.request.db
foo = 'bar'
return foo
Note that self is not defined at the time when you want the class to refer to itself for the assignment to work. This is because (in addition to being named arbitrarily), self refers to instances and not classes. At the time that the suspect line of code attempts to run, there is as of yet no class for it to refer to. Not that it would refer to the class if there was.
In a method, you can always use type(self). That will get the subclass of MyClass that created the current instance. If you want to hard-code to MyClass, that name will be available in the global scope of the methods. This will allow you to do everything that your example would allow if it actually worked. E.g, you can just do MyClass.some_attribute inside your methods.
You probably want to modify the class attributes after class creation. This can be done with decorators or on an ad-hoc basis. Metaclasses may be a better fit. Without knowing what you actually want to do though, it's impossible to say.
UPDATE:
Here's some code to do what you want. It uses a metaclass AutoViewConfigMeta and a new decorator to mark the methods that you want view_config applied to. I spoofed the view_config decorator. It prints out the class name when it's called though to prove that it has access to it. The metaclass __new__ just loops through the class dictionary and looks for methods that were marked by the auto_view_config decorator. It cleans off the mark and applies the view_config decorator with the appropriate class name.
Here's the code.
# This just spoofs the view_config decorator.
def view_config(route=''):
def dec(f):
def wrapper(*args, **kwargs):
print "route={0}".format(route)
return f(*args, **kwargs)
return wrapper
return dec
# Apply this decorator to methods for which you want to call view_config with
# the class name. It will tag them. The metaclass will apply view_config once it
# has the class name.
def auto_view_config(f):
f.auto_view_config = True
return f
class AutoViewConfigMeta(type):
def __new__(mcls, name, bases, dict_):
#This is called during class creation. _dict is the namespace of the class and
# name is it's name. So the idea is to pull out the methods that need
# view_config applied to them and manually apply them with the class name.
# We'll recognize them because they will have the auto_view_config attribute
# set on them by the `auto_view_config` decorator. Then use type to create
# the class and return it.
for item in dict_:
if hasattr(dict_[item], 'auto_view_config'):
method = dict_[item]
del method.auto_view_config # Clean up after ourselves.
# The next line is the manual form of applying a decorator.
dict_[item] = view_config(route=name)(method)
# Call out to type to actually create the class with the modified dict.
return type.__new__(mcls, name, bases, dict_)
class simpleObject(object):
__metaclass__ = AutoViewConfigMeta
class Test(simpleObject):
#auto_view_config
def activateTheView(self):
foo = 'bar'
print foo
if __name__=='__main__':
t = Test()
t.activateTheView()
Let me know if you have any questions.
Python has an "explict is better than implicit" design philosophy.
Many languages have an implicit pointer or variable in the scope of a method that (e.g. this in C++) that refers to the object through which the method was invoked. Python does not have this. Here, all bound methods will have an extra first argument that is the object through which the method was invoked. You can call it anything you want (self is not a keyword like this in C++). The name self is convention rather than a syntactic rule.
Your method myFunction defines the variable self as a parameter so it works. There's no such variable at the class level so it's erroring out.
So much for the explanation. I'm not aware of a straightforward way for you to do what you want and I've never seen such requirement in Python. Can you detail why you want to do such a thing? Perhaps there's an assumption that you're making which can be handled in another way using Python.
self is just a name, your self in this case is a class variable and not this for the object using which it is called,
self is treated as a normal variable and it is not defined, where as the self in the function comes from the object used for calling.
you want to treat the object reference in self as a class variable which is not possible.
self isn't a keyword, it's just a convention. The methods are attributes of the class object (not the instance), but they receive the instance as their first argument. You could rename the argument to xyzzy if you wanted and it would still work the same way.
But (as should be obvious) you can't refer to a method argument outside the body of the method. Inside a class block but outside of any method, self is undefined. And the concept wouldn't even make sense -- at the time the class block is being evaluated, no instance of the class can possibly exist yet.
Because the name self is explicitly defined as part of the arguments to myFunction. The first argument to a method is the instance that the method was called on; in the class body, there isn't an "instance we're dealing with", because the class body deals with every possible instance of the class (including ones that don't necessarily exist yet) - so, there isn't a particular object that could be called self.
If you want to refer to the class itself, rather than some instance of it, this is spelled self.__class__ (or, for new-style classes in Py2 and all classes in Py3, type(self)) anywhere self exists. If you want to be able to deal with this in situations where self doesn't exist, then you may want to look at class methods which aren't associated with any particular instance, and so take the class itself in place of self. If you really need to do this in the class body (and, you probably don't), you'll just have to call it by name.
You can't refer to the class itself within the class body because the class doesn't exist at the time that the class body is executed. (If the previous sentence is confusing, reading up about metaclasses will either clear this up or make you more confused.)
Within an instance method, you can refer to the class of the instance with self.__class__, but be careful here. This will be the instance's actual class, which through the power of inheritance might not be the class in which the method was defined.
Within a class method, the class is passed in as the first argument, much like instances are the first argument to instance methods:
class MyClass(object):
#classmethod
def foo(cls):
print cls.__name__
MyClass.foo() # Should print "MyClass"
As with instance methods, the actual class might differ due to inheritance.
class OtherClass(MyClass):
pass
OtherClass.foo() # Should print "OtherClass"
If you really need to refer to MyClass within a method of MyClass, you're pretty much going to have to refer to it as MyClass unless you use magic. This sort of magic is more trouble than it is worth.

Categories

Resources