Please help me in understanding Class in Python - python

I am newbie and finding it very hard to grasp the syntax of Class in python. I have a background of C/C++, java and objective C. A very big difference which i am noticing in python is that you don't explicitly declare the "data members" in the class and you just randomly add them? And it leads to quite big confusion.
Let say i have a class
class MyClass:
def __int__(self, a, b):
self.a = a
self.b = b
And then when i initiate the object.
myobject = MyClass(10,10)
And just after some time for some reason i come to know that i need another parameter in this class but i dont wanted to initiate that using constructor because it will be initiated by another function depending on the some particular condition, so in whole mess of code that will be only point that variable actually get birth. is not the case when i will be checking the code while debugging or reviewing it for some other reason it will be confusing?

In short, Yes.
You're right. Python lets you add (and remove!) members from objects at will, at any time. There's nothing special about a constructor that allows it to do anything that other functions can't.
If you want to be sure that all instances of your class have the same members at all times, then by all means assign them all in the constructor, using a sentinel value like None for ones that don't have a meaningful value yet, and avoid adding new members outside the constructor.
It's up to you how you manipulate your objects, and if you want to do that in a static fashion then that's fine, or if you want to take advantage of the ability to add and remove members at arbitrary times, that's fine too. Python itself doesn't impose (m)any rules.

You should really use some . in your text :p
Could you mean:
class MyClass:
def __int__(self, a, b, c=None):
self.a = a
self.b = b
self.c = c
one = MyClass(1,2)
one.c # None
two = MyClass(1,2,3)
two.c # 3

class MyClass:
def __int__(self, a, b):
self.a = a
self.b = b
self.c = None #This line is optional
def set_c(self, c):
self.c = c
Some people prefer to list all the attributes in the __init__. You don't have to, but there are any number of reasons you might choose to.
Maybe it improves your editor's ability to understand your code for highlighting or completion.
Maybe it is just a style that you prefer.

Related

Is it possible develop or create class like python in R?

In python, there have a very clear structure about class, for example like blow.
The self concept is very convenience avoid the duplicate variable.
And it can also write the function to change the variable inside.
class object():
def __init__(self):
self.a
self.b
......
def addoneinside(self):
self.a = a + 1
In R, I need to use <- change the value after return. Maybe I can use %<>% to do this.
But in python, I can do object.addoneinside(), then the object.a will become 2 automatically.
I really like r because the data process is really easy and intuition.
Is this possible to change R code style like python?

Python Inherited Classes all return same random number?

I have a few classes with almost identical contents, so I tried two methods to copy the classes and their attributes over. The classes copy correctly, but the randint function is only invoked in the main class, so the same number is output every time. Is there any way to recalculate the random number for each class?
class a:
exampleData = random.randint(1,100)
b = type('b', a.__bases__, dict(a.__dict__))
class c(a):
pass
For example if a.exampleData = 50, b.exampleData and c.exampleData would be the same. Is there any way around this?
Edit -- Part of my program displays characters with random stats each time, and the class contains the stats associated with each character. The random numbers pick the stats out of a list, but the same stats are being chosen, instead of being random in each class. I may not be explaining this right, so basically:
data = [stat1,stat2,stat3,ect,,]
data[random.randint(1,3)]
When you write this:
b = type('b', a.__bases__, dict(a.__dict__))
… you're just copying a.__dict__. Since a.__dict__ is just {'exampleData': 50}, the new copy that ends up as b.__dict__ is also going to be {'exampleData': 50}.
There are many ways you could get a new random number. The simplest is to just create a new random number for b explicitly:
bdict = dict(a.__dict__)
b['exampleData'] = random.randint(1,100)
b = type('b', a.__bases__, bdict)
If you want to create a bunch of classes this way, you can wrap that up in a function:
def make_clone(proto, name):
clonedict = dict(proto.__dict__)
clonedict['exampleData'] = random.randint(1,100)
return type(name, proto.__bases__, clonedict)
You can make that factory function more complicated if you want to be (see namedtuple for a pretty extreme example).
You could wrap that behavior up in a decorator:
def randomize(cls):
cls.exampleData = random.randint(1,100)
#randomize
class a:
pass
b = randomize(type('b', a.__bases__, dict(a.__dict__)))
Notice that I had to call the decorator with normal function-call syntax here, because there's no declaration statement to attach an #decorator to.
Or you can wrap it up in a metaclass:
class RandomMeta(type):
def __new__(mcls, name, bases, namespace):
d = dict(namespace)
d['exampleData'] = random.randint(1,100)
return type.__new__(mcls, name, bases, d)
class a(metaclass=RandomMeta):
pass
b = type(a)('b', a.__bases__, dict(a.__dict__))
Notice that we have to call type(a) here, the same way a class definition statement does, not the base metaclass type.
Also notice that I'm not taking **kwds in the __new__ method, and I'm calling type.__new__ directly. This means that if you try to use RandomMeta together with another metaclass (besides type), you should get an immediate TypeError, rather than something that may or may not be correct.
Meanwhile, I have a suspicion that what you're really trying to do here is build a prototype-based inheritance system, a la Self or JavaScript on top of Python's class-based system. While you can do that by using a special Prototype metaclass and a bunch of class objects, it's a whole lot simpler to just have a Prototype class and a bunch of instance objects. The only advantage to the metaclass approach is that you can use class statements (misleadingly, but conveniently) to clone prototypes, and you're explicitly not doing that here.
While my other answer covers the question as asked, I suspect it's all completely unnecessary to the OP's actual problem.
If you just want to create a bunch of separate objects, which each have a separate value for exampleData, you just want a bunch of instances of a single class, not a bunch of separate classes.
A class is a special kind of object that, in addition to doing all the normal object stuff, also works as a factory for other objects, which are instances of that class. You don't need a, b, and c to all be factories for for different kinds of objects, you just need them to be different objects of the same type. So:
class RandomThing:
def __init__(self):
self.exampleData = random.randint(1,100)
a = RandomThing()
b = RandomThing()
… or, if you want to make sure b is the same type of thing as a but don't know what type that is:
b = type(a)()
That's as fancy as you need to get here.
See the official tutorial on Classes (or maybe search for a friendlier tutorial, because there are probably better ones out there).

calling an object with inheritance in python

First things first, I'm reasonably new to python, but I have been working hard and doing lots of tutorials and sample projects to get better, so, if I'm missing something obvious, I appologize.
I've been trying to figure this out for a while now, and I've done a number of searches here and through the googles, but I can't quite figure out how to turn the examples I've found into what I'm looking for, so I was hoping someone here could give me a push in the right direction.
class Super1:
def __init__(self,artib1,atrib2,atrib3):
self.atrib1 = atrib1
self.atrib2 = atrib2
self.atrib3 = atrib3
class Sub1(Super1):
def __init__(self,atrib4,atrib5,atrib6)
self.atrib4 = atrib4
self.atrib5 = atrib5
self.atrib6 = atrib6
okay, so what I'm having trouble figuring out is, in the tutroials I've done, they said that I could call on the class like this:
spam = Super1("eggs","foo","bar")
and if I input
print spam.atrib1
it would spit out
eggs
What I want to do is make spam = Sub1, but I don't know how to call it so that I can set all the 'attrib's the way I did with Super1.
I looked up a number of 'multiple inheritance' examples, but I can't seem to reconcile the examples into my own needs. Most of the tutorials don't have more than 1 atribute, or often have the sub 'override' the atributes of the super.
I also checked into composition, and I'm not sure that's exactly what I'm looking for for this part of my project, but I do know that I will need it in later parts.
If anyone can point me in the right direction, that would be great.
You need to call the parent class's constructor Super1.__init__(self)
You also need to allow Sub1 to take the arguments for the parent class's constructor.
With the modifications above, your code becomes:
class Sub1(Super1):
def __init__(self, artib1, atrib2, atrib3, atrib4, atrib5, atrib6)
Super1.__init__(self, artib1, atrib2, atrib3)
self.atrib4 = atrib4
self.atrib5 = atrib5
self.atrib6 = atrib6
However, rather than calling the parent class's constructor yourself, you should use the super built-in function:
super(Sub1, self).__init__(artib1, atrib2, atrib3)
That way, you don't have to hard-code the name of the parent class in each sub-classes constructor. This allows you to easily refactor your code. Another added benefit of using super is that will automatically deal with the sticky details of multiple-inheritance problems such as "diamond inheritance".
One more piece of advice is that if you don't know the amount of positional arguments ahead of time that the super class will take, you can use the *args syntax:
class Sub1(Super1):
def __init__(self, atrib4, atrib5, atrib6, *args)
super(Sub1, self).__init__(*args)
self.atrib4 = atrib4
self.atrib5 = atrib5
self.atrib6 = atrib6
If Sub1 inherits from Super1, that's supposed to mean it is a Super1 (with some extra stuff added, or with some customizations). But you can't remove things, so Sub1 must
contain everything a Super1 contains
initialize the Super1 part of itself by calling super(Sub1,self).1.__init__(self, ...) in its own constructor.
So, if you your super class has a member a, whose value is passed to its constructor, your subclass also has (inherits) a member a, and must somehow pass its value to the superclass constructor.
Whether that means
class Sub1(Super1):
def __init__(self, a, b, c, d, e, f):
super(Sub1, self).__init__(a,b,c)
self.d=d
self.e=e
self.f=f
or whether there's some relationship between the super and subclass arguments (or the subclass hard-codes some of the superclass arguments, or ...) depends on your code.
If you call spam = Super1("eggs","foo","bar"). It will call Super class constructor.
The problem is if you want to create a instance for the Sub1 you should spam = Super1("eggs","foo","bar",atrib4,atrib5,atri6). Also you have to change the constructor for the Sub1 as:
def __init__(self,atrib1,atrib2,atrib3,atrib4,atrib5,atrib6):
Super1.__init__(self,atrib1,atrib2,atrib3)
self.atrib4 = atrib4
self.atrib5 = atrib5
self.atrib6 = atrib6`

Overriding an inner function of a method in python

That is a kind of best practices question.
I have a class structure with some methods defined. In some cases I want to override a particular part of a method. First thought on that is splitting my method to more atomic pieces and override related parts like below.
class myTest(object):
def __init__(self):
pass
def myfunc(self):
self._do_atomic_job()
...
...
def _do_atomic_job(self):
print "Hello"
That is a practical-looking way to solve the problem. But since I have too many parameters that is needed to be transferred to and revieced back from _do_atomic_job(), I do not want to pass and retrieve tons of parameters. Other option is setting these parameters as class variables with self.param_var etc but those parameters are used in a small part of the code and using self is not my preferred way of solving this.
Last option I thought is using inner functions. (I know I will have problems in variable scopes but as I said, this is a best practise and just ignore them and think scope and all things about the inner functions are working as expected)
class MyTest2(object):
mytext = ""
def myfunc(self):
def _do_atomic_job():
mytext = "Hello"
_do_atomic_job()
print mytext
Lets assume that works as expected. What I want to do is overriding the inner function _do_atomic_job()
class MyTest3(MyTest2):
def __init__(self):
super(MyTest3, self).__init__()
self.myfunc._do_atomic_job = self._alt_do_atomic_job # Of course this do not work!
def _alt_do_atomic_job(self):
mytext = "Hollla!"
Do what I want to achieve is overriding inherited class' method's inner function _do_atomic_job
Is it possible?
Either factoring _do_atomic_job() into a proper method, or maybe factoring it
into its own class seem like the best approach to take. Overriding an inner
function can't work, because you won't have access to the local variable of the
containing method.
You say that _do_atomic_job() takes a lot of parameters returns lots of values. Maybe you group some of these parameters into reasonable objects:
_do_atomic_job(start_x, start_y, end_x, end_y) # Separate coordinates
_do_atomic_job(start, end) # Better: start/end points
_do_atomic_job(rect) # Even better: rectangle
If you can't do that, and _do_atomic_job() is reasonably self-contained,
you could create helper classes AtomicJobParams and AtomicJobResult.
An example using namedtuples instead of classes:
AtomicJobParams = namedtuple('AtomicJobParams', ['a', 'b', 'c', 'd'])
jobparams = AtomicJobParams(a, b, c, d)
_do_atomic_job(jobparams) # Returns AtomicJobResult
Finally, if the atomic job is self-contained, you can even factor it into its
own class AtomicJob.
class AtomicJob:
def __init__(self, a, b, c, d):
self.a = a
self.b = b
self.c = c
self.d = d
self._do_atomic_job()
def _do_atomic_job(self):
...
self.result_1 = 42
self.result_2 = 23
self.result_3 = 443
Overall, this seems more like a code factorization problem. Aim for rather lean
classes that delegate work to helpers where appropriate. Follow the single responsibility principle. If values belong together, bundle them up in a value class.
As David Miller (a prominent Linux kernel developer) recently said:
If you write interfaces with more than 4 or 5 function arguments, it's
possible that you and I cannot be friends.
Inner variables are related to where they are defined and not where they are executed. This prints "hello".
class MyTest2(object):
def __init__(self):
localvariable = "hello"
def do_atomic_job():
print localvariable
self.do_atomic_job = do_atomic_job
def myfunc(self):
localvariable = "hollla!"
self.do_atomic_job()
MyTest2().myfunc()
So I can't see any way you could use the local variables without passing them, which is probably the best way to do it.
Note: Passing locals() will get you a dict of the variables, this is considered quite bad style though.

Explaining Python variable scope

I'm teaching myself Python and I was translating some sample code into this
class Student(object):
def __init__( self, name, a,b,c ):
self.name = name
self.a = a
self.b = b
self.c = c
def average(self):
return ( a+b+c ) / 3.0
Which is pretty much my intended class definition.
Later in the main method I create an instance and call it a:
if __name__ == "__main__" :
a = Student( "Oscar", 10, 10, 10 )
That's how I find out that the variable a declared in main is available to the method average and to make that method work, I have to type self.a + self.b + self.c instead.
What's the rationale for this?
Barenames (like a, b, c) are always scoped as local or global (save for nested functions, which are nowhere around in your code). The rationale is that adding further scopes would needlessly make things more complicated -- e.g, if in your self.a = a the barename a could be scoped to mean what you appear to want (equivalent to self.a) then the assignment itself would be meaningless (assigning a name to itself), so you'd need further complicated rules.
Just using qualified names (like self.a) when you want something different than barenames' simple, straightforward, and optimized behavior, is by far the simplest approach -- perfectly workable, no complicated rules whatsoever, and allows the compiler to optimize things effectively (since e.g. a barename's scope is always lexically determined, not dependent on dynamically varying characteristics of the environment). So, besides perhaps nostalgia for other language with more complicated scoping rules, there's really no rationale for complicating the semantics of barenames.
There are several reasons, though the main one is from the Zen of Python: "Explicit is better than implicit." In a language like C++, a method on the class always has an implicit argument this which is pushed onto the stack every time the method is called. In this case, when an instance variable b exists as well as a global variable b, then the user may just refer to b referring to one without realizing that the other will be used. So Python forces you to be explicit about your scope to avoid confusion.
With that being said, there are other reasons as well. For example, I may define a function outside of a class and then attach it to a class at runtime. For example:
def log(self):
print "some library function requires all objects to have a log method"
print "unfortunately we're using the Student class, which doesn't have one"
print "this class is defined in a separate library, so we can't add the method"
print "fortunately, we can just add the method dynamically at runtime"
Student.log = log
Here the fact that self is explicit makes it trivial for us to define a function outside of a class and then attach it to that class. I don't do this sort of thing incredibly often, but it's EXTREMELY useful when I do.
Here's an even more complex example; suppose we want to define a class inside another class, such as for the purposes of unit testing:
class SomeUnitTests(TestCase):
def test_something(self):
class SomeMockObject(SomeActualObject):
def foo(self2):
self.assertEqual(self2.x, SOME_CONSTANT)
some_lib.do_something_with(SomeMockObject)
Here the presence of an explicit self (which we can call whatever we want, it doesn't have to be self) allows to to distinguish between the self of the inner and outer classes. Again, this isn't something I do frequently, but when I do then it's incredibly useful.
All instance variables should be called using self

Categories

Resources