Python official name for an attribute that is not a method - python

According to my understanding the data members of objects in Python are referred to as 'attributes'.
Attributes that are callable are referred to as an object's 'methods', but I couldn't find a name for non-callable attributes, such as val in the following example:
class C:
def __init__(self):
self.val = 42. # How would this be called?
def self.action():
"""A method."""
print(self.val)
I am sure different people may call val different things like 'field' or 'variable' but I am interested in an official name.

Surprisingly hard to find official information on this topic. After reading this article I do believe it should simply be called Class Variable and Instance Variable.
Attributes, Properties, Methods and Variables
Attribute is the collection name for the three names Property, Method and Variable. The latter two are prefixed by either Class or Instance. A property can only belong to the Class.
class Foo:
a = 1
def __init__(self):
self.b = 2
#property
def c(self):
return 3
#classmethod
def d(cls):
return 4
def e(self):
return 5
Foo.a # Class Attribute: Class Variable
Foo().a # Class Attribute: Class Variable
Foo().b # Instance Attribute: Instance Variable
Foo.c # Class Attribute: Property
Foo.d # Class Attribute: Class Method
Foo().d # Class Attribute: Class Method
Foo.e # Class Attribute: Class Method
Foo().e # Instance Attribute: Instance Method
Sources
Difference between Class and Instance methods
How do I assign a property to an instance in Python?
What's the difference between a Python "property" and "attribute"?
https://docs.python.org/3/tutorial/classes.html#python-scopes-and-namespaces
Diagram made in Creately

I'm not sure if one exists, but I'd suggest just "instance attribute".
Features about this naming:
It excludes methods. Methods are all callable class attributes, so this wording excludes all methods.
It includes callable instance attributes. Consider the following code:
class Container:
def __init__(self, item):
self.item = item
c = Container(x)
c.item # is an "instance attribute"
c.item == x # True
Note that c.item is an "instance attribute" regardless of whether or not it's callable. I think this is behaviour you're after, but I'm not sure.
It excludes non-callable class attributes, e.g.
class SomeClass:
x = 5 # Is not an "instance attribute"
It includes per-instance attributes, e.g.
obj.x = 5
obj.x # Is an "instance attribute"
In the end, all of these features may be positives or negatives depending on specifically what you want. But I don't know specifically what you want, and this is as close as I can get. If you can provide more information, I can give a better suggestion.

Related

We can create instance attrbitues for objects in Python. Can we create instance methods (not class Methods) as well in Python?

How To create a methods which are common to a particular object just like creating instance attrbitue obj.instance_attribute
A method which belongs specifically for a single object ?
The link contains the code. I need to create method only for this object and not all instance of class.
Creating class methods and attribute. The instance attrbitue. How to create instance methods
class A():
def init(self):
self.class_variable = 999999
def class_methods(self):
#available to all object
print("Hey")
obj = A()
obj.class_variable
999999
obj.class_methods()
Hey
obj.instance_attribute = 40404040 #common to particular object
obj.instance_attribute
40404040
#a method which is common to only this object
obj.new_method():
SyntaxError: invalid syntax
obj.new_mehtod(self):
SyntaxError: invalid syntax
I think you are mixing up terminology. Every "normal" method is a instance method - that means it applies the function without affecting any other instances of this class. To reference the instance, use the passed self keyword.
Defining a method for a single instance inside the generator/ class definition does not make sense in an OOP-context. If you create a car class, every instance of this class should be able to access its methods, like drive().
The only way to add a unique function is to add it after instantiating the object. This can be done with the types.MethodType method, which binds the function to the class instance:
from types import MethodType
def fly(self):
print(f"i, {self.name}, can fly")
class Car:
def __init__(self, name):
self.name = name
car_1 = Car("car one")
car_2 = Car("car two")
car_1.fly = MethodType(fly, car_1)
car_1.fly() # i, car one, can fly
car_2.fly() # AttributeError: 'Car' object has no attribute 'fly'
As you can see, car_1 has the class fly, which references car_1's name, while car_2 does not have this function.
But you should seriously reconsider what you are trying to achieve here.

Difference between methods and attributes in python

I am learning python and doing an exercise about classes. It tells me to add an attribute to my class and a method to my class. I always thought these were the same thing until I read the exercise. What is the difference between the two?
Terminology
Mental model:
A variable stored in an instance or class is called an attribute.
A function stored in an instance or class is called a method.
According to Python's glossary:
attribute: A value associated with an object which is referenced by
name using dotted expressions. For example, if an object o has an
attribute a it would be referenced as o.a
method: A function which is defined inside a class body. If called as an attribute of an instance of that class, the method will get the instance object as its first argument (which is usually called self). See function and nested scope.
Examples
Terminology applied to actual code:
a = 10 # variable
def f(b): # function
return b ** 2
class C:
c = 20 # class attribute
def __init__(self, d): # "dunder" method
self.d = d # instance attribute
def show(self): # method
print(self.c, self.d)
e = C(30)
e.g = 40 # another instance attribute
A method is an attribute, but not all attributes are methods. For example, if we have the class
class MyClass(object):
class_name = 'My Class'
def my_method(self):
print('Hello World!')
This class has two attributes, class_name and my_method. But only my_method is a method. Methods are functions that belong to your object. There are additional hidden attributes present on all classes, but this is what your exercise is likely talking about.
A quick,simplified explanation.
Attribute == characteristics.
Method == operations/ actions.
For example, Let's describe a cat (meow!).
What are the attributes(characteristics) of a cat?
It has different breed, name, color, whether they have spots...etc.
What are methods (actions) of a cat?
It can meow, climb, scratch you, destroy your laptop, etc.
Notice the difference, attributes define characteristics of the cat.
Methods, on the other hand, defines action/operation (verb).
Now, putting the above definition in mind, let's create an object of class 'cat'...meowww
class Cat():
To create attributes, use def init(self, arg1, arg2) - (as shown below).
The 'self' keyword is a reference to a particular instance of a class.
def __init__(self, mybreed, name):
# Attributes
self.breed = mybreed
self.name = name
# Operations/actions --> methods
def kill_mouse(self):
print('Insert some method to kill mouse here')
Notice (above) 'mybreed' is an input argument that the user need to specify, whereas self.breed is an attribute of the instance assigned to 'mybreed' argument. Usually, they're the same (e.g. breed for both, self.breed = breed). Here, it's coded differently to avoid confusion.
And attributes are usually written as 'self.attribute_name' (as shown above).
Now, methods are more like actions, or operations, where you define a function inside the body of a class to perform some operation, for example, killing a mouse. A method could also utilize the attributes that you defined within the object itself.
Another key difference between a method and attribute is how you call it.
For example, let's say we create an instance using the above class we defined.
my_cat = Cat()
To call an attribute, you use
my_cat.name
or
my_cat.breed
For methods, you call it to execute some action. In Python, you call method with an open and close parenthesis, as shown below:
my_cat.kill_mouse()
A method is a function defined in the class. An attribute is an instance variable defined in the class.
Example:
class Example(object):
def __init__(self, name):
self.name = name
def hello(self):
print 'Hi, I am ' + self.name
Here hello is a method, and name is an attribute.
class example:
global a
# a=0
def __init__(self,x,y):
self.fname=x
self.lname=y
def show(self):
return "first name: {} & Last name: {}".format(self.fname,self.lname)
obj1=example('reyan','ishtiaq')
obj2=example('ishtiaq','reyan')
print('method associated with obj1: '+ obj1.show())
print('method associated with obj2: '+ obj2.show())
obj1.a=20
obj2.a=30
print(obj1.a)
print(obj2.a)
output:
method associated with obj1: first name: reyan & Last name: ishtiaq................
method associated with obj2: first name: ishtiaq & Last name: reyan................
20
30
#Below u can see that I made a class called "example" with two class attributes:
variable1 and variable2.
class example():
def init(self, variable1, variable2):
self.variable1 = variable1
self.variable2 = variable1
i did not construct a method inside this class. Notice that variable1 comes first and after comes variable2 inside the init():
#below i created an object "object1" with the example class. I created the example class with two arguments "variable1" and "variable2". "self" does not count), so i have to pass two arguments when calling the example class. I gave two variables "10" and "20".
object1 = example(10,20)
with the code below i just get the value of the first argument, which is 10.
print(object1.variable1)

How to change variable of main class from inherited class?

I need to change object variable directly from inherited class.
Here is my code example:
class A(object):
def __init__(self,initVal=0):
self.myVal = initVal
def worker(self):
self.incrementor = B()
self.incrementor.incMyVal(5)
class B(A):
def incMyVal(self,incVal):
super().myVal += incVal
obj = A(5)
print(obj.myVal)
obj.worker()
print(obj.myVal)
But it doesn't work:
AttributeError: 'super' object has no attribute 'myVal'
I also tried to use global/nonlocal keywords with my variable in B class, but no luck.
In my main case, the B class is an event handler. And it should change the attribute of an object when an event fires. So I'm not able to use return in the incMyVal method.
super() can only search for class attributes in the class MRO, not instance attributes. myVal is set on an instance of the class, not on a class itself.
There is only ever one instance; it doesn't matter if code from class A or a derived class is altering attributes on an instance, it is just one namespace.
However, in your case, you shouldn't even be using inheritance. You are trying to use an independent, second instance to alter the attributes of an instance of A. Class inheritance doesn't give you access to instances of the base class like this.
Refactor B to take an instance of A, then act on that instance:
class B:
def __init__(self, ainstance):
self.ainstance = ainstance
def incMyVal(self, incVal):
self.ainstance.myVal += incVal
Note that B is not a subclass of A here; it is not a (specialised) object of the same type at all; it is a different kind of thing, something that increments attributes of another object.
Pass in the instance when you create an instance of B:
def worker(self):
self.incrementor = B(self)
self.incrementor.incMyVal(5)
This does create a circular reference, which can keep objects alive for longer than perhaps needed. You may want to use a weak reference instead:
import weakref
class B:
def __init__(self, ainstance):
self.ainstance_ref = weakref.ref(ainstance)
def incMyVal(self, incVal):
ainstance = self.ainstance_ref()
if ainstance is not None:
ainstance.myVal += incVal
Now B instances only hold a weak reference to their A instance, and will do nothing if that instance no longer exists.

Python Class Inheritance, __init__ and cls

The desired output of the code is that I have a class variable Team.stuff which has one entry holding the b instance, and the Player.stuff variable should be empty. Instead I get an error...
class Player:
stuff=[]
def __init__(self):
cls.stuff.append(self)
class Team(Player):
def __init__(self):
super(Team, self).__init__()
b=Team()
ERROR
cls.stuff.append(self)
NameError: global name 'cls' is not defined
I could pass the cls variable in the Team.__init__(), but I'm not sure if that is the "correct" way, and more importantly the Player.__init__() would need a class variable, and I'm not sure on the syntax on how to do that.
class Player(object):
stuff=[]
def __init__(self):
self.stuff.append(self)
class Team(Player):
def __init__(self):
super(Team, self).__init__()
b = Team()
print(Team.stuff)
prints (something like)
[<__main__.Team object at 0xb7519dec>]
Remember that cls is not a keyword in Python. Rather it is a convention for the first argument of a method when that method is supposed to be a class function and not one that is called on a particular instance of something.
If you want stuff to be an attribute of a function, you have to define it like so: self.stuff=[].
And then, when you refer to it in methods, do it with the self keyword as well: self.stuff.append(..).
The reason for this is that cls in your __init__ function is not defined. The argument names self and cls are just naming conventions. In reality, you could name them foo and bar for an instance and a class method respectively, and foo would point at the class instance whilst bar would point a the class itself.
Moreover, self.stuff would be valid as when searching for an attribute, if an object does not have an attribute of such name in it's __dict__ dictionary, the __dict__ of it's class is looked instead. If both are missing, further lookups are done according to mro order.
Notice that, once you set an attribute stuff on an object instance, it will shadow the class definition.
Explained by example:
class MyClassA(object):
stuff = []
class MyClassB(MyClassA):
def __init__(foobar):
# `foobar` points at the instance of `MyClassB` class.
# MyClassA.stuff gets `1` object appended to it.
foobar.stuff.append(1)
# This should print '[1]'
print foobar.stuff
# `MyClassB` object gets a _new_ attribute named `stuff` pointing at a list.
foobar.stuff = []
# This should print '[]'.
print foobar.stuff

Python: Overriding a member with a property?

I was trying to override a member of a Python (2.7) class with a property, as shown in the following code:
class Base:
def __init__(self):
self.foo = 1
class Derived(Base):
foo = property(lambda self: 2)
print Derived().foo
However, the last line prints 1 instead of 2. From the way I thought properties are supposed to work (ie., easily change a member to a function later on), this seems counter-intuitive to me. Am I missing something? Is there some workaround?
This doesn't work because you aren't using a new-style class. Properties are descriptors which only work on new-style classes. What your code is doing is this:
You create a class Derived with a class attribute foo. Then when you create an instance of the class, Base.__init__ takes over since Derived has no __init__ and you add the instance attribute foo which takes precedence to the class attribute.
If you change:
class Base: #old style class
to:
class Base(object): #new style class
You'll run into an entirely new problem, mainly that your property doesn't have an appropriately defined setter, so when you do self.foo = 1 in Base.__init__ you'll get an AttributeError

Categories

Resources