nameTuple and class parameters - python

My lecturer wrote some code and I have no idea how to read it and google isn't helping, can someone please clarify how this code interacts.
yield Arc(tail_node, head = tail_node - 1, label="1down", cost=1)
Is the method call for the class
class Arc(namedtuple('Arc', 'tail, head, label, cost')):
The class Arc contains no methods, and no __init. I have no clue how these two are interacting since I thought class parameters accepted another class, and it made the current class a subclass or abstract etc.

The collections.namedtuple function is a class factory. It takes some parameters and returns a class. The class inherits from tuple, but its values are also accessible by name as attributes (not only by index).
The Arc class you show uses namedtuple to create its base class. You could equivalently write it with separate statements, giving the base class it's own name:
Base = namedtuple('Arc', 'tail, head, label, cost') # this creates a class
class Arc(Base): # this class inherits from the base class
pass
If the Arc class doesn't have any methods of its own, there wouldn't be much point in defining it at all (you'd just use the name Arc instead of Base for the class returned from namedtuple). I'm guessing there is some more code in the Arc class, just not anything relevant to your question. The behavior inherited from the base class is enough to create instances using positional or keyword arguments, so the yield statement you show doesn't need any additional code.

Related

Understanding Abstract Base Classes in Python

I was reading about abstract base class and came across https://www.python-course.eu/python3_abstract_classes.php website. I got general idea about them but I found two statement contradictory of each other.
Subclasses of an abstract class in Python are not required to implement abstract methods of the parent class.
and
A class that is derived from an abstract class cannot be instantiated unless all of its abstract methods are overridden.
My understanding of first statement is, derived class are not required to implement abstract method of the parent class which is wrong. I made a sample program to check that.
from abc import ABC, abstractmethod
class AbstractClassExample(ABC):
#abstractmethod
def do_something(self):
print("Some implementation!")
class AnotherSubclass(AbstractClassExample):
def just_another_method(self):
super().do_something()
print("The enrichment from AnotherSubclass")
x = AnotherSubclass() # TypeError: Can't instantiate abstract class AnotherSubclass with abstract methods do_something
x.do_something()
I would like an explanation of what the first statement means(preferably with examples).
Your code demonstrates that the second statement is true. It doesn't show that the first statement is false.
In your code, you are trying to instantiate AnotherSubclass, which is not allowed because AnotherSubclass does not implement all the abstract methods. The second statement says this.
However, if you delete the last two lines, i.e. not instantiating AnotherSubclass, then your code will produce no errors when you try to run it. This shows that the first statement is true - subclasses of abstract classes that doesn't implement all its abstract methods are allowed to exist.
You can write another subclass of AnotherSubclass called YetAnotherClass, this time implementing the abstract method, and you will be able to instantiate YetAnotherClass. Note that your program now does something, and AnotherSubclass is still allowed to exist.

How to access class variable of super class without explicit super class name

As the title stated, I want to get how to accessing class variable of super class without explicit super class name. Or whether that is possible.
I am NOT talking about accessing instance variable, but class variable.
For example, if i want to override a class variable in the following example, I have to explicitly use Parent.class_variable.
class Parent():
class_variable = 'this_is_class_variable'
class Child(Parent):
class_variable = Parent.class_variable + ' in child class'
Thank you in advance.
You can't easily do what you want to do, because Child isn't a class until after you're done defining it. Since it's not a class yet, it doesn't have any parents.
Potentially you could do it with some kind of metaprogramming; could be fun to hack on. The approach I'd take is to write a proxy object that represents an attribute of the parent class. It needs to accumulate the operations that are to be performed on it (such as concatenation using + as in your example) rather than performing them immediately. A metaclass or decorator then goes through the finalized class looking for attributes that are instances of this class and forces their evaluation in the context of the parent class (which can be determined from the class's __mro__ attribute).
This is lot of work, so I'll leave an actual implementation as an exercise for the reader. ;-)

Why call a base class constructor from inherited class

I have been trying to understand this use case, where we often call a base class constructor from the inherited class, is the sole purpose of doing that is to just ensure that the base class is initialized? Or, would there be other possible use cases?
class Base:
def __init__(self):
print('Base.__init__')
class A(Base):
def __init__(self):
super().__init__()
print('A.__init__')
is the sole purpose of doing that is to just ensure that the base class is initialized?
Well yes, but what do you mean, just?
Assuming your base class has a reason to exist, it must do something.
Unless it's just a convenient collection of #staticmethod functions, whatever it does might depend on its __init__ having been called, because that's how class objects work.
Even if your base class has an empty __init__ today, it's sensible to call it, in case that changes in the future.
Or, would there be other possible use cases?
The use case is to make sure that the base class part of your object is correctly initialized. Without that, you can't safely call any of its non-static methods.
In principle your base class could do something tricksy in its __init__ (starting a background thread, or registering the instance with some singleton, or ... whatever). So yes, there could be effects other than just assigning instance variables, but this is still part of initializing an object of that base class.
In C++ or Java, the compiler will require you to call the base class constructor (either by automatically inserting a zero-argument call or by giving you an error).
Python requires you to call it yourself, as it is written:
If a base class has an __init__() method, the derived class’s __init__() method, if any, must explicitly call it to ensure proper initialization of the base class part of the instance
The reason why is a principle of object oriented design. An A "is-a" Base, which could also be written equivalently as an A "has-a" Base. Unless you specifically want to interfere with the implementation of Base, you have to allow the object to be initialized as designed. Skipping the constructor will leave the Base object improperly initialized, disappointing anyone who expects it to behave as a Base object ought to.
When overriding a method besides the constructor, it is the programmer's discretion to delegate to the base class implementation or to override it entirely. This can still lead to incorrect behavior --- several API docs I can think of pepper the documentation with "If you override this method, you should call super" for various methods.
The point of this is to initialize all the stuff the base class usually initializes. For example,
class Base:
def __init__(self, number):
print('Base.__init__')
self.number = number
class A(Base):
def __init__(self, number, string):
super().__init__(number)
self.string = string
print('A.__init__')
In this code example it's more obvious. When A calls the base constructor, the base constructor will initialize all of the stuff needed, such as self.number. This way, the rest of A's initialization function can build on top of the base initialization function without any retyping. In this example, A is building on top of Base by adding self.string on top of self.number.

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.

What does abstract mean in this context?

I need some help in understanding a python concept.
class TilePuzzleProblem(search.Problem):
""" This class is the class for the NxN - blanks tile puzzle problem """
def __init__(self, N, blanks, initial, goal):
""" Initialize """
search.Problem.__init__(self, initial, goal)
self.N = N
self.blanks = blanks
def successor(self, state):
""" Generate the successors of the given state. Returns a list of (move, successor) pairs"""
abstract
def h(self, node):
abstract
Currently the code hangs at the abstract part of the function h(...), but I have no idea what abstract means, hence can not understand what the problem is.
This is a trick described here. There's not keyword abstract in Python, so, if you won't override this method in some subclass, it'll cause NotImplementedError.
An abstract method is one which a class doesn't implement, making it an abstract class; subclasses must override all abstract methods (i.e., provide concrete implementations) to be concrete classes, i.e., ones for which you can make instances. The normal way in Python to express "this method is abstract" is to have the method's body be raise NotImplementedError.
For more about the general concept, apart from its specifics in Python, see wikipedia.
So, formally, you need to subclass this and implement those two methods marked as "abstract". (Depending on your TA's hints, he or she may actually mean that you should replace the word "abstract" with a working body of code, but that would be quite a stretch with respect the normal meaning of "abstract" in OOP!-).
An abstract function is a function with no implementation. It's a placeholder, just there to fill out the class contract so that you know what methods subclass should provide. What you need to do here is create a descendant of TilePuzzleProblem and fill in your own implementation of h. If you want to run it as is, create a descendant and make your h do nothing.
Abstract means the class must be inherited. Abstract or "base" classes are there to provide a base type which you can extend through inheritance. You cannot instantiate an abstract class, only the classes that inherit it.
See this Wikipedia article for more information.
One reason you'd want to use an abstract base class is if you want to categorize or group your sub-types. For example, Car, Truck and Plane would all inherit from the Vehicle abstract base class. You can't just instantiate a "vehicle", you have to instantiate a car, truck or plane. Being abstract protects it from being instantiated.

Categories

Resources