I recently went to an interview and did some little programming test where they had a simple two class script that would calculate the area, side length, etc.. Of a shape it looked something like this:
class Shape(object):
def __init__(self, side1, side2, side3, side4):
self.side1 = side1
...
#abstractmethod
def calc_area(self):
pass
class Triangle(Shape):
def calc_area(self):
... etc..
One of the questions they asked me was, if we ran help(Shape(3, 5, 5, 6)) what would happen assuming all objects have been initialized? my answer was, nothing because there's no docstring or __doc__. It appears that I was marked down on this answer and I can't seem to understand why? Was I incorrect in thinking that nothing would happen when running help()?
There are a couple of things in your description of the code that could be what they were expecting you to mention. It's not completely obvious to me which of these is an error of your memory of the code, and which is the real issue, but they are both things to think about:
The Shape class you show has an #abstractmethod in it. If it had a properly defined metaclass (something derived from abc.ABCMeta), you wouldn't be able to create any instances from it. Only concrete subclasses that override each of the abstract methods could be instantiated. So they may have expected you to say "you can't call help() on Shape(...) because the latter causes a TypeError.
Calling help on an instance will give you a description of each of the class's methods, even if it doesn't have a docstring. If a docstring exists, it will be displayed first, but the documentation for the methods (and descriptors, etc.) will always follow.
If you look at the source of pydoc.Helper class (especially its help() method), which is essentially what you get when you call help(), you'll see that it will still get the basic structure of your object using the inspect module and a couple of other tricks.
The goal being, of course, to provide at least object/function signature to other developers if the original code writers didn't bother with writing the docs. Personally, I don't see the reason of help() existing in the global namespace anyway, but I understand why they've placed it both from a historical and philosophical perspective.
That being said, whoever interviewed you was, IMO, a jerk - this doesn't really have to do much with programming but with nitpicking which is, may I say, quite un-Pythonic. That is, assuming that they weren't trying to get you on the #abstractmethod descriptor, of course, which might be a valid question.
Related
Fellow pythonistas,
We adopted Python type hints in a new project.
The project itself is composed of couple of modules that don't share a common repository, but they do have interdependencies. Since it is a pure algorithmic research project, we decided to use decopuled components that program through an interface, so we have an abstract class that all those that want to substitute current module for another one, have to comply with this interface.
Say,
class ClusteringInterface(ABC):
def __init__(self, n_groups: int, data_generator: Generator[Dict, None, None]):
self.n_groups = n_groups
self.data_generator = data_generator
...
#abstractmethod
def foo(self):
pass
Now, I do want to accept anything that complies with ClusteringInterface, so it implements foo methods and complies with the init function. Can I somehow define a custom type so that mypy will indeed throw an error when something pretends to be ClusteringInterface, but is really something completely different?
I have seen Raymond Hettinger lecture about Abstract classes and I understand that python itself cannot guarantee that.
So the more general question would be: What is the recommended solution so that I actually can enforce compliance with an interface? I realize that the question is a little bit too broad, but I don't really know where to look for more information.
Simple question. What would be the most pythonic way to make a class unable to be instantiated.
I know this could be done by overriding new __new__ and raising an exception there. Is there a better way?
I am kinda looking in the abstract class direction. However, I will NOT use this class as a base class to any other classes. And will NOT have any abstract methods defined in the class.
Without those, the abstract class does not raise any exceptions upon instantiation.
I have looked at this answer. It is not what I am looking for.
Is it possible to make abstract classes in Python?
Edit:
I know this might not be the best approach, but it is how I solved something I needed. I think it is a simple question, that can have a yes + explanation or no answer. Answers/comments that basically amount to, you should not be asking this question make very little sense.
what you're after is being able to just call something like, math.sin(x) right?
you make it a static method. and you just simply don't make any instances.
#staticmethod
def awesome_method(x): return x
if you're thinking why can't you actually do a = math()
because math, isn't a class. it's a separate script with all those functions in it.
so you may want to make a separate script with all your static things in it. ;)
if you want everything in the same script, then it's just local variables. and if you're like me, you'd rather them be organised properly with classes, looks like you'd probably be best just making a normal class, and creating just one instance of it
I've recently started working at a company doing work in Python, and in their code they have a class which defines a handful of functions that do nothing, and return nothing. Code that is pretty much exactly
...
...
def foo(self):
return
I'm really confused as to why anyone would do that, and my manager is not around for me to ask. Would one do this for the sake of abstraction for child classes? A signal that the function will be overridden in the future? The class I'm looking at in particular inherits from a base class that does not contain any of the functions that are returning nothing, so I know that at least this class isn't doing some kind of weird function overriding.
Sometimes, if a class is meant to be used interchangeably with another class in the API, it can make sense to provide functions that don't do much (or anything). Depending on the API though, I would typically expect these functions to return something like NotImplemented.
Or, maybe somebody didn't get enough sleep the night before and forgot what they were typing ... or got called away to a meeting without finishing what they were working on ...
Ultimately, nobody can know the actual reason without having a good knowledge of the code you're working with. Basically -- I'd wait for your boss or a co-worker to come around and ask.
If the functions have meaningful names, then it could be a skeleton for future intended functionality.
Let's say we have the following classes:
class Duck(object):
pass
class OldFashionedDuck(Organism, Duck):
def look(self):
self.display_biological_appearance()
def walk(self):
self.keep_balance_on_two_feet()
def quack(self):
self.make_noise_with_lungs("Quack!")
class ArtificialDuck(Robot, Duck):
def look(self):
self.display_imitation_biological_appearance()
def walk(self):
self.engage_leg_clockwork()
def quack(self):
self.play_sound("quack.au")
In this example, OldFashionedDuck and ArtificialDuck have no common implementation, but by construction they will both return True for isinstance(..., Duck).
This is not perfect, but it is something that I thought might help respect both duck typing, and (via empty mixin inheritance) allow isinstance(). In essence it offers a contract to meet an interface, so it's not really calling isinstance() based on the class that does all the work, but based on an interface that anyone can opt-in to.
I've seen articles based on "isinstance() considered harmful," because it breaks duck typing. However, I at least as a programmer would like to know, if not necessarily where an object gets a function from, but whether it implements an interface.
Is this approach useful, and if so can it be improved upon?
I've seen articles based on "isinstance() considered harmful," because it breaks duck typing. However, I at least as a programmer would like to know, if not necessarily where an object gets a function from, but whether it implements an interface.
I think you're missing the point.
When we talk about "duck typing", what we really mean is not formalizing our interfaces. What you're trying to do, therefore, boils down to attempting to answer the question "how can I formalize my interface while still not formalizing my interface?".
We expect an object that was given to us to implement an interface - one that we described, not by making a base class, but by writing a bunch of documentation and describing behaviour (and if we're feeling especially frisky, setting up some kind of test suite) - because we said that this is what we expect (again in our documentation). We verify that the object implements the interface by attempting to use it as though it does, and treating any resulting errors as the caller's responsibility. Calling code that gives us the wrong object is naughty, and that's where the bug needs to be fixed. (Again, tests help us track these things down.)
In short, testing isinstance(this_fuzzball_that_was_handed_to_me, Duck) doesn't really help matters:
It could pass the isinstance check, but implement the methods in a way that violates our expectations (or, say, return NotImplemented). Only real testing will do here.
It could pass the check, but actually completely fail to implement one or more of the methods; after all, the base Duck doesn't contain any implementations, and Python has no reason to check for them in a derived class.
Perhaps more importantly, it could fail the check, even though it's a perfectly usable-as-a-duck fuzzball. Maybe it's some unrelated object that had quack, walk and look functions directly, manually attached to it as attributes (as opposed to them being attributes of its class, which become methods when looked up).
Okay, so, "don't do that", you say. But now you're making more work for everyone; if clients don't always opt in, then it's useless and dangerous for the duck-using code to make the check. And meanwhile, what are you gaining?
This is related to the EAFP principle: don't try to figure out whether something is a Duck by looking at it; figure out if it's a Duck by treating it as a Duck and dealing with the gory mess if it isn't.
But if you don't care about the duck typing philosophy, and absolutely must force some semblance of rigor onto things, you might be interested in the standard library abc module.
Even though I don't want to overestimate this term, but: Your approach is not pythonic. Do duck-typing, or don't do it.
If you want to be sure that your implementation of a "interface" implements everything it should: test it!
For smaller projects, it's easy to remember what you need. And you can simply try it.
I agree that for larger projects, or even cooperation in teams, it's better to make sure that your type has everything it needs. In such a scenario, you definitely should use unit-tests to make sure your type is complete. Even without duck-typing, you need tests, so probably you won't need any extra-tests.
Guido van Rossum has talked about some interesting thoughts about duck-typing in this talk. It's so inspiring, and definitely worth watching.
Note: I'm not talking about preventing the rebinding of a variable. I'm talking about preventing the modification of the memory that the variable refers to, and of any memory that can be reached from there by following the nested containers.
I have a large data structure, and I want to expose it to other modules, on a read-only basis. The only way to do that in Python is to deep-copy the particular pieces I'd like to expose - prohibitively expensive in my case.
I am sure this is a very common problem, and it seems like a constant reference would be the perfect solution. But I must be missing something. Perhaps constant references are hard to implement in Python. Perhaps they don't quite do what I think they do.
Any insights would be appreciated.
While the answers are helpful, I haven't seen a single reason why const would be either hard to implement or unworkable in Python. I guess "un-Pythonic" would also count as a valid reason, but is it really? Python does do scrambling of private instance variables (starting with __) to avoid accidental bugs, and const doesn't seem to be that different in spirit.
EDIT: I just offered a very modest bounty. I am looking for a bit more detail about why Python ended up without const. I suspect the reason is that it's really hard to implement to work perfectly; I would like to understand why it's so hard.
It's the same as with private methods: as consenting adults authors of code should agree on an interface without need of force. Because really really enforcing the contract is hard, and doing it the half-assed way leads to hackish code in abundance.
Use get-only descriptors, and state clearly in your documentation that these data is meant to be read only. After all, a determined coder could probably find a way to use your code in different ways you thought of anyways.
In PEP 351, Barry Warsaw proposed a protocol for "freezing" any mutable data structure, analogous to the way that frozenset makes an immutable set. Frozen data structures would be hashable and so capable being used as keys in dictionaries.
The proposal was discussed on python-dev, with Raymond Hettinger's criticism the most detailed.
It's not quite what you're after, but it's the closest I can find, and should give you some idea of the thinking of the Python developers on this subject.
There are many design questions about any language, the answer to most of which is "just because". It's pretty clear that constants like this would go against the ideology of Python.
You can make a read-only class attribute, though, using descriptors. It's not trivial, but it's not very hard. The way it works is that you can make properties (things that look like attributes but call a method on access) using the property decorator; if you make a getter but not a setter property then you will get a read-only attribute. The reason for the metaclass programming is that since __init__ receives a fully-formed instance of the class, you actually can't set the attributes to what you want at this stage! Instead, you have to set them on creation of the class, which means you need a metaclass.
Code from this recipe:
# simple read only attributes with meta-class programming
# method factory for an attribute get method
def getmethod(attrname):
def _getmethod(self):
return self.__readonly__[attrname]
return _getmethod
class metaClass(type):
def __new__(cls,classname,bases,classdict):
readonly = classdict.get('__readonly__',{})
for name,default in readonly.items():
classdict[name] = property(getmethod(name))
return type.__new__(cls,classname,bases,classdict)
class ROClass(object):
__metaclass__ = metaClass
__readonly__ = {'a':1,'b':'text'}
if __name__ == '__main__':
def test1():
t = ROClass()
print t.a
print t.b
def test2():
t = ROClass()
t.a = 2
test1()
While one programmer writing code is a consenting adult, two programmers working on the same code seldom are consenting adults. More so if they do not value the beauty of the code but them deadlines or research funds.
For such adults there is some type safety, provided by Enthought's Traits.
You could look into Constant and ReadOnly traits.
For some additional thoughts, there is a similar question posed about Java here:
Why is there no Constant feature in Java?
When asking why Python has decided against constant references, I think it's helpful to think of how they would be implemented in the language. Should Python have some sort of special declaration, const, to create variable references that can't be changed? Why not allow variables to be declared a float/int/whatever then...these would surely help prevent programming bugs as well. While we're at it, adding class and method modifiers like protected/private/public/etc. would help enforce compile-type checking against illegal uses of these classes. ...pretty soon, we've lost the beauty, simplicity, and elegance that is Python, and we're writing code in some sort of bastard child of C++/Java.
Python also currently passes everything by reference. This would be some sort of special pass-by-reference-but-flag-it-to-prevent-modification...a pretty special case (and as the Tao of Python indicates, just "un-Pythonic").
As mentioned before, without actually changing the language, this type of behaviour can be implemented via classes & descriptors. It may not prevent modification from a determined hacker, but we are consenting adults. Python didn't necessarily decide against providing this as an included module ("batteries included") - there was just never enough demand for it.