It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I need some help defining certain terms. I've been programming for a few months (python and JavaScript) and still have certain troubles understanding some of the programming terms
This is what am I working on now:
from datetime import datetime
now = datetime.now()
month1 = now.month
year1 = now.year
day1 = now.day
print "%s/%s/%s" % (month1, year1, day1)
It's very straight forward and it's easy to perform and understand, but I have no idea what classes, functions and methods are. Every time I Google an answer it's usually some big definition using even more programming words I don't understand. I need some basic definitions and preferable some examples. I hate having to ask this kind of question and any help would be much appreciated. Thanks.
def thisIsAFunction(inputNumber):
oneMore= inputNumber+ 1
return oneMore
this is a function, that returns one more than the input number.
so later on in your code you call it like this
anotherVariable = thisIsAFunction(5)
then when you want to: print anotherVariable and it will print 6
classes are similar, but more broad and encompasing
class thisIsaClass:
someVar = 1
def __init__(self, inputNumber):
self.inputNumber = inputNumber
this just defined an object called "thisIsaClass".... to create an object....
>>> a = thisIsaClass(1) #creating one 'thisisaclass' object called a
>>> b = thisIsaClass(2) #another called b
>>>
>>> a.inputNumber # getting inputnumber from a
1
>>> b.inputNumber
2
>>> a.someVar #someVar doesnt have 'self' in front of it so its not referring to its own someVar, its referring to its classes someVar
1
>>> b.someVar
1
>>> thisIsaClass.someVar = 3
>>> a.someVar #see? it changed it for all of th someVars
3
>>> b.someVar #because its the same someVar
3
>>> thisIsaClass.inputNumber #and THIS one doesnt actually have a "inputNumber" because it only belongs to the actual objects
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: class thisIsaClass has no attribute 'inputNumber'
if thats confusing, then the best way to look at a class is to relate it to people.
class human:
def __init__(self, name, height, age):
self.name = name
self.height = height
self.age = age
beth = human('beth','64 inches', 19)
beth.age
19
the __init__ is a METHOD, because it is a definition within a class. (Honestly i have no idea why its called that... but it is) if we were to define another function(but its in a class so its a method lol) below init like
def birthday(self):
self.age = self.age+1
then everytime we wanted to give beth a birthday, we would just type
beth.birthday()
beth.age
20
A function is a thing that can do something and/or return a result, which depends on the parameters you invoke it with.
How you make and use a function:
def function(foo):
...
result = function("bar")
You asked about a class, but first I'll explain an object.
An object contains some data and can do some things. The things it can do are functions, and functions associated with an object are in particular called methods. In addition to the parameters, the behavior of a method can, and usually does, depend on the object's data, and can update the data. In some programming languages, you cannot directly access the data in an object or maybe some but not all of it; you can only ask the object to do the things it does, and it might or might not offer setting the value of its data as one of the things it does. However, in Python you can directly access the data, but some still consider it good practice not to.
A class is a group of objects that have the same type of data and same set of things that they can do. It also provides a starting point to create new objects of that class.
How to make a class with a method:
class Foo:
def method(self, parameter):
...
How to make an object of the class:
f = Foo()
How to call a method of the object:
f.method(argument)
It may be easier to understand everything if you define your own classes, instances, methods, and functions.
class Car(object):
def set_odometer(self, miles):
self.miles = miles
def get_odometer(self):
return self.miles
def drive(self, miles):
self.miles += miles
def joyride(stolen_car):
stolen_car.drive(100)
print 'Insert Yello song here'
new_car = Car()
new_car.set_odometer(0)
print 'Now it has', new_car.get_odometer(), 'miles!'
joyride(new_car)
print 'Now it has', new_car.get_odometer(), 'miles!'
So:
Car is a class. A class defines a new type. Just as int defines integers, and str defines strings, Car defines a new kind of thing that you can drive (and do other things to).
Each time you create a new instance of the Car class, it's an object. For example, new_car is an instance of Car. That is, it's a thing you can drive (and do other things to).
Car.drive is a method of the Car class. This means that new_car.drive is a method of the new_car instance. Notice the self parameter in the definition of drive. When you call new_car.set_odometer(100), that self parameter refers to new_car.
joyride is a function. It's not part of any class, and it has no self parameter. That's really the only difference between methods and functions.
(In fact, under the covers, in Python, a method is just a way of putting a function and an instance together. For example, new_car.drive.im_self is new_car. But don't worry about that.)
Notice that inside of joyride, stolen_car is the same object that you passed in—in this case, new_car. So, you can call stolen_car.drive(), and it's driving new_car.
In real code, you usually won't bother with methods like set_odometer and get_odometer, because you can access data attributes, aka members, like miles just as easily as you can access methods:
new_car = Car()
new_car.miles = 0
print 'Now it has', new_car.miles, 'miles!'
However, you do often set initial values for your attributes in a special __init__ method. For example:
class Car(object):
def __init__(self):
self.miles = 0
def drive(self, miles):
self.miles += miles
def joyride(stolen_car):
stolen_car.drive(100)
print 'Insert Yello song here'
new_car = Car()
print 'Now it has', new_car.get_odometer(), 'miles!'
joyride(new_car)
print 'Now it has', new_car.get_odometer(), 'miles!'
So, how does that apply to your example?
Well, your example is a bit confusing. You don't call any normal instance methods at all. But let's go through it step by step.
from datetime import datetime
datetime is a class. How do you know that? Well, you could look at the code inside the datetime module, but, more simply, just print it:
>>> from datetime import datetime
>>> print datetime
<type 'datetime.datetime'>
Loosely speaking, a type and a class are the same thing. (A type can actually be written in custom C code, instead of with a class, and so on, so this isn't exactly true, but it's close enough.)
now = datetime.now()
datetime.now is a special kind of thing known as a classmethod. Normal methods can only be called on instances, but class methods are instead called on classes. Don't worry about this for now. The important thing is that what it returns is an object, an instance of type datetime. Again, you can test that, by printing out its type:
>>> now = datetime.now()
>>> print type(d)
<type 'datetime.datetime'>
And then you just access some data attributes of the object:
month1 = now.month
year1 = now.year
day1 = now.day
These attributes were set by the now method, much the same way that a normal class sets attributes inside its __init__ method.
Related
This question already has answers here:
How to access (get or set) object attribute given string corresponding to name of that attribute
(3 answers)
Closed 3 years ago.
I have a Python class that have attributes named: date1, date2, date3, etc.
During runtime, I have a variable i, which is an integer.
What I want to do is to access the appropriate date attribute in run time based on the value of i.
For example,
if i == 1, I want to access myobject.date1
if i == 2, I want to access myobject.date2
And I want to do something similar for class instead of attribute.
For example, I have a bunch of classes: MyClass1, MyClass2, MyClass3, etc. And I have a variable k.
if k == 1, I want to instantiate a new instance of MyClass1
if k == 2, I want to instantiate a new instance of MyClass2
How can i do that?
EDIT
I'm hoping to avoid using a giant if-then-else statement to select the appropriate attribute/class.
Is there a way in Python to compose the class name on the fly using the value of a variable?
You can use getattr() to access a property when you don't know its name until runtime:
obj = myobject()
i = 7
date7 = getattr(obj, 'date%d' % i) # same as obj.date7
If you keep your numbered classes in a module called foo, you can use getattr() again to access them by number.
foo.py:
class Class1: pass
class Class2: pass
[ etc ]
bar.py:
import foo
i = 3
someClass = getattr(foo, "Class%d" % i) # Same as someClass = foo.Class3
obj = someClass() # someClass is a pointer to foo.Class3
# short version:
obj = getattr(foo, "Class%d" % i)()
Having said all that, you really should avoid this sort of thing because you will never be able to find out where these numbered properties and classes are being used except by reading through your entire codebase. You are better off putting everything in a dictionary.
For the first case, you should be able to do:
getattr(myobject, 'date%s' % i)
For the second case, you can do:
myobject = locals()['MyClass%s' % k]()
However, the fact that you need to do this in the first place can be a sign that you're approaching the problem in a very non-Pythonic way.
OK, well... It seems like this needs a bit of work. Firstly, for your date* things, they should be perhaps stored as a dict of attributes. eg, myobj.dates[1], so on.
For the classes, it sounds like you want polymorphism. All of your MyClass* classes should have a common ancestor. The ancestor's __new__ method should figure out which of its children to instantiate.
One way for the parent to know what to make is to keep a dict of the children. There are ways that the parent class doesn't need to enumerate its children by searching for all of its subclasses but it's a bit more complex to implement. See here for more info on how you might take that approach. Read the comments especially, they expand on it.
class Parent(object):
_children = {
1: MyClass1,
2: MyClass2,
}
def __new__(k):
return object.__new__(Parent._children[k])
class MyClass1(Parent):
def __init__(self):
self.foo = 1
class MyClass2(Parent):
def __init__(self):
self.foo = 2
bar = Parent(1)
print bar.foo # 1
baz = Parent(2)
print bar.foo # 2
Thirdly, you really should rethink your variable naming. Don't use numbers to enumerate your variables, instead give them meaningful names. i and k are bad to use as they are by convention reserved for loop indexes.
A sample of your existing code would be very helpful in improving it.
to get a list of all the attributes, try:
dir(<class instance>)
I agree with Daenyth, but if you're feeling sassy you can use the dict method that comes with all classes:
>>> class nullclass(object):
def nullmethod():
pass
>>> nullclass.__dict__.keys()
['__dict__', '__module__', '__weakref__', 'nullmethod', '__doc__']
>>> nullclass.__dict__["nullmethod"]
<function nullmethod at 0x013366A8>
While learning about how classes work in Python I came across a class definition example which behaved kind of strangely in my eyes.
The purpose of the example was to demonstrate how the behaviour of a static variable can be achieved in Python. The example was written as follows:
class MemberCounter:
members = 0
def init(self):
MemberCounter.members += 1
m1 = MemberCounter()
m1.init()
m2 = MemberCounter()
m2.init()
after setting up the class and creating the objects, I printed the values of the 'members' attribute. These were the results:
MemberCounter.members = 2
m1.members = 2
m2.members = 2
And that's when I got confused. While I was expecting for 'MemberCounter.members = 2' the two other results made no sense to me - why would both of 'm1' and 'm2' objects' 'members' value be equal to 2? I thought that both of the values should have been 0 - if the only attribute that was chaged is the 'members' attribute which was attached to the MemberCounter class why would it cause any change to the own unique 'members' value of each of the class' objects. It looks like the fact that the 'members' attribute is addresed like 'MemberCounter.members += 1' in the init() function of each object, completely overrides the unique values which m1.members and m2.members refer to and redirects their pointers to the MemberCounter.members value making all the three pointers point at the same value
==> m1.members = m2.members = MemberCounter.members.
Moreover, I have tried defining the class in an opossite way (Increasing self.members instead of MemberCounter.members):
class MemberCounter:
members = 0
def init(self):
self.members += 1
m1 = MemberCounter()
m1.init()
m2 = MemberCounter()
m2.init()
This definition yielded logical results (which got me curious about the above mentioned strange behaviour even more):
MemberCounter.members = 0
m1.members = 1
m2.members = 1
In short, I was curious about why the first class definition behaves in such a strange way? Why the mere 'MemberCounter.members += 1' statement completely erased 'm1.members' and 'm2.members' own unique value and made it equal to the MemberCounter.members value.
I hope I was able to clearly present my problem and I will be extremly happy to get an insight about this strange behaviour :)
That you can read a static attribute with instance.attribute notation as alternative to the more natural class.attribute notation, is an intended feature in Python.
From the documentation:
Both static data and static methods (in the sense of C++ or Java) are supported in Python.
For static data, simply define a class attribute. To assign a new
value to the attribute, you have to explicitly use the class name in
the assignment:
class C:
count = 0 # number of times C.__init__ called
def __init__(self):
C.count = C.count + 1
def getcount(self):
return C.count # or return self.count
c.count also refers to C.count for any c such that
isinstance(c, C) holds, unless overridden by c itself or by some
class on the base-class search path from c.__class__ back to C.
Caution: within a method of C, an assignment like self.count = 42
creates a new and unrelated instance named “count” in self’s own dict.
Rebinding of a class-static data name must always specify the class
whether inside a method or not:
C.count = 314
The paragraph just below the first code block explains your doubts. The "Caution" paragraph explains what you found logical.
Looking at the code I have below as an example. Why is it I get the error "Float object not callable" when using print statement 1 but not print statement 2? what do I need to do to my class if I was wanting to make print statement 1 work?
var1 = float(input())
class ExampleClass(object):
def __init__(self, thing1):
self.getThing1 = thing1
def getThing1(self):
return self.getThing1
a = ExampleClass(var1)
print(str(a.getThing1())) #print statement 1 that doesn't work
print(str(a.getThing1)) #print statement 2 that does work
You are trying to use getThing1 as a method name and an attribute. You declare a method getThing1, but then you assign self.getThing1 = thing1. So getThing1 isn't a method anymore; it's the value of thing1.
Perhaps you meant this:
class ExampleClass(object):
def __init__(self, thing1):
self.thing1 = thing1
def getThing1(self):
return self.thing1
However, getXXX methods are not the convention in Python. If you need a method wrapping your attribute, you should make it a property.
This:
class ExampleClass(object):
def __init__(self, thing1):
---> self.getThing1 = thing1
shadows this:
def getThing1(self):
return self.getThing1
Python functions are objects don't live in a distinct namepsace, so to make a long story short you cannot have an attribute and a method by the same name.
The solution is simple: don't use getThing1 as an attribute name - specially since "get" is a verb so it's a poor name for a value.
Also note that Python has a string support for computed attributes so you don't need systematic getters/setters for attributes. You can start with a plain attribute and turn it into a computed one later if the need arises.
Doing a class and finished with the rest less this one. Any guidance is appreciated. I have derived part of the question where I am stuck with to keep it short. I have also attached my working. Question as follows:
Create a class with 1 variable in it holding its own properties.
Provide the following 3 methods:
getvariable1() - use return key tp return value of property 1
setvariable1() - This should allow new value to be specified for property 1 - additional parameter needed to accept input.
printerfun() - to print values of the variables for the object.
Create your own object of the class and call get & set methods for the object created. Use printerfun() method to check if the codes works.
My working:
class animal:
horns = 2
def printerfun(self):
print getHorns()
def getHorns(self): #don't get where I should call this
return self.horns
def setHorns(horns):
self.horns = horns
animal_1 = animal()
F1 = raw_input('Please enter number of horns: ')
setHorns(F1)
Not sure what the question is, but anyway...
You should write a __init__ member function to create the initial member variables:
class animal:
def __init__(self):
self.horns = 2
Your code creates a class variable, not a normal member variable.
Then change the horns with:
animal_1.setHorns(F1)
Your code doesn't say which animal you want to change the variable to.
I have the following code:
def f():
class XYZ:
# ...
cls = type('XXX', (XYZ, ), {})
# ...
return cls
I am now using it as follows:
C1 = f()
C2 = f()
and it seems to work fine: C1 is C2 returns False, there's no conflict between the class attributes of the two classes, etc.
Question 1
Why is that? How is it possible that C1 and C2 are both shown as class
<'__main__.XXX'>
and yet not the same class?
Question 2
Is there some problem with the fact that I have two identical names for two different classes?
Question 3
I would like to be able to write instead:
f('C1')
f('C2')
with the same effect. Is it possible?
Question 4
If I want C1 to look like a regular class, not main.XXX, is it ok to say:
C1.__name__ = '__main__.C1'
Question 3
To have cls.__name__ be anything you want, (with a nod to delnan's suggestion)
def f(clsname):
class XYZ:
# ...
XYZ.__name__ = XYZ
# ...
return XYZ
Question 1
The reason that c1 is not c2 is that they are two different objects stored at two different locations in memory.
Question 4
Try an answer to question 1 and see how it works out for you
Question 2
It can complicate debugging that their class attributes __name__ share a common value and this is bad enough to take pains to avoid. (see question 3). I would maintain though that they don't have the same name. One is named C1 and the other is named C2 (at least in the scope you are showing. If you were to pass them to a function, then there name in that scope would be the same as the name of parameter that they were passed through)
In fact, I'm so sure that they don't have the same name that trying to tell me otherwise is likely to cause me to turn the music up louder and pretend I can't hear you.
In response to comment
It can be done but it's just wrong. I'll illustrate anyway because it's illuminating:
def f(clsname):
class XYZ(object):
pass
XYZ.__name__ = clsname
globals()[clsname] = XYZ
f('C1')
f('C2')
print C1
print C2
This just works by sticking the class in the globals dict keyed by clsname. But what's the point? You can stick it in the globals dict under any name in fact because this is just another assignment. You are best off just returning the class from the function and letting the caller decide what name to give the class in it's own scope. You still have the __name__ attribute of the class set to the string you pass to the function for debugging purposes.
Actually, you don't need to the cls = ... line at all.
>>> def f():
... class C:
... pass
... return C
...
>>> f() is f()
False
Reason: class (as well as e.g. def) defines a new class each time it is encountered = each time the function is called.
As for cls.__name__, it's really no semantic difference. The name is useful for debugging (you don't expose it directly to the user, do you?) and introspection, but it shouldn't be an issue. But if you absolutely want to have different names, you can change cls.__name__ before returning (also note that after C.__name__ = 'foo', C.__name__ == '__main__.foo'!).
At question 3: It would be possible to inject it directly into global namespace... don't do this. It has no advantages, only disatvantages: nonobvious side effects, bad style, the fact it's a hack at all, etc!