Initializing a Python object - python

I am trying to teach myself object oriented programming in Python with the book "Python 3, Object Oriented Programming", by Dusty Phillips. On pages 54 and 55 he creates a class called Note and encourages the reader to repeat the example and import the module from the interpreter with the following commands. However, when I do, I type the n1 = command I get the message from the interpreter "TypeError: object() takes no parameters. Am I missing something in the implementation of this object, or did the book give a faulty example? Mind you the example and the lines typed into the interpreter are taken exactly from the book, at least I think I made no errors in copying the lines. This is different initialization syntax than C++, which makes me wonder if the author gave a bad example, but in the book example it looks as if he is trying to initialize with a call to the object directly and the object is supposed to recognize the text that gets passed to memo. Also I tried to run the example in python 2.7.9 and 3.4.2 to see if this was a version issue.
Interpreter lines
from notebook import Note
n1 = Note("hello first") # the code execution gets stopped here fur to the error
n2 = Note("hello again")
n1.id
n2.id
import datetime
# store the next available id for all new notes
last_id = 0
class Note:
'''Represent a note in the notebook. Match against a
string in searches and store tags for each note.'''
def _init_(self, memo, tags=''):
'''initialize a note with memo and optional
space-seperated tags. Automatically set the note's
creation date and a unique id.'''
self.memo = memo
self.tags = tags
self.creation_date = datetime.date()
global last_id
last_id += 1
self.id = last_id
def match(self, filter):
'''Determine if this note matches the filter
text. Return True if it matches, False otherwise.
Search is case sensitive and matches both text and
tags'''
return filter in self.memo or filter in self.tags

Maybe do what Christian said: Use __init__ instead of _init_. You need to have double underscores not single underscores. You can look at the Python Docs.

You are missing double underscores in the special __init__ method. You only have single underscores.
You might also consider having Note explicitly inherit from object, i.e. class Note(object).

Related

Can a Python object attribute have its own attribute?

I'm a little confused by what I'm seeing in the unittest file of this Exercism exercise. These are some of the tests that are run to check the validity of my program. (You create a PhoneNumber object in the main program.)
def test_area_code(self):
number = PhoneNumber("2234567890")
self.assertEqual(number.area_code, "223")
def test_pretty_print(self):
number = PhoneNumber("2234567890")
self.assertEqual(number.pretty(), "(223) 456-7890")
def test_pretty_print_with_full_us_phone_number(self):
number = PhoneNumber("12234567890")
self.assertEqual(number.pretty(), "(223) 456-7890")
I know how to create the number attribute for my class objects, but what do number.area_code and number.pretty() mean? What makes this valid Python code? I tried just creating a value like self.number.area_code = <something here>, but that didn't work. What exactly is this called and how do I create it?
Thanks!
Edit: This is another part of the unittest file:
def test_cleans_the_number(self):
number = PhoneNumber("(223) 456-7890").number
self.assertEqual(number, "2234567890")
def test_cleans_numbers_with_dots(self):
number = PhoneNumber("223.456.7890").number
self.assertEqual(number, "2234567890")
def test_cleans_numbers_with_multiple_spaces(self):
number = PhoneNumber("223 456 7890 ").number
self.assertEqual(number, "2234567890")
Doesn't this part mean that number is an attribute? This is why I misunderstood the previously quoted section. The unittest file seems to be using number in two different ways, and I didn't catch it in the former part!

TypeError: gettext() missing 1 required positional argument: 'self' - python

I'm new to python and I'm tring to make a class for a modul which checking curses in texts.
can someone help please?
import urllib
class Checktext:
def __init__(self, text):
self.text = text
def gettext(self):
file = open(self.text, "r")
filetext = open.read()
for word in filetext.split():
openurl = urllib.request.urlopen("http://www.wdylike.appspot.com/?q=" + word)
output = openurl.read()
truer = "true" in str(output)
print(truer)
s = Checktext(r"C:\Users\Tzach\.atom\Test\Training\readme.txt")
Checktext.gettext()
You declared s as a new Checktext object, so you need to call s.gettext() not an un-instantiated Checktext.gettext(), as that has no self to refer to
The urllib is a package. You have to import the module request that is located in the package:
import urllib.request
The open(filename) return a file object. You want to call the method of that object:
filetext = file.read()
And as G. Anderson wrote, you want to call s.gettext() instead of Checktext.gettext(). The self inside is actually equal to the s outside. If you want to be weird then you actually can use also:
Checktext.gettext(s)
Notice the s passed as your missing parameter. Here Python actually reveals how the Object Oriented things are implemented internally. In majority of OO languages, it is carefully hidden, but calling a method of an object is always internally translated as passing one more special argument that points to the instance of the class, that is the object. When defining a Python method, that special argument is explicitly named self (by convention; you can name it differently -- you can try as the lecture, but you should always keep that convention).
Thinking about it thoroughly, you can get the key idea of the hidden magic of an OO language syntax. The instance of the class (the object) is actually only a portion of memory that stores the data part, and that is passed to the functions that implement the methods. The Checktext.gettext is actually the function, the s is the object. The s.gettext() is actually only a different way to express exactly the same. AS s is the instance of the Checktext class, the fact is stored inside the s. Therefore, the s.gettext() creates the illusion that the rigth code will be called magically. It fits with the trained brain better than the function approach if the s is thought as a tangible something.

How to convert buildbot Property to string value

Problem:
I am trying to figure out how to convert a buildbot Property into a string value. I really don't have much experience with buildbot other than what I have read in the docs and someone elses code.
The issue is I have a Property that contains a path. I need to get the path as a string so that I can use some python functions such as 'split' and 'basename' to retrieve specific elements of the path.
What I Have Tried:
There is a property mapped like so
"artifact.output":"S3://dev/artifacts/out/package1.tar.gz"
When I call path.os.basename(util.Property("artifact.output")) it complains that Property has no 'rfind' method. I also tried using util.Interpolate but again, it has the same issue. Finally, I tried str(util.Property("artifact.output")) but it just outputs Property("artifact.output").
Question:
Is it possible to retrieve a buildbot Property as a string value?
note: I was only able to find one other post from someone back on 2014 asking the same thing but no answer.
A Property is not a string by itself, but it's a class that implements an IRenderable interface. This interface defines something, that can be "rendered" into a string when needed. To render a Property or any renderable (eg. the util.Interpolate object), you need a an IProperties provider.
The question is where to get such provider and how to render it. When implementing your own step, you can use the Build instance that you can access from self.build as such provider and use it to render the property.
class ExampleBuildStep(BuildStep):
def __init__(self, arg, **kwargs):
"""
Args:
arg - any string, Property or any renderable that will be rendered in run
"""
self.arg = arg
super().__init__(**kwargs)
#defer.inlineCallbacks
def run(self):
# the renderedcommand will be the string representation of the self.arg
renderedcommand = yield self.build.render(self.arg)
In the example above, the ExampleBuildStep takes an argument arg that will be rendered inside the run() function. Note that the arg does not have to be property, it can be a tring as well. You can now create use the build step with renderables:
step = ExampleBuildStep(util.Property("artifact.output"))
step = ExampleBuildStep(util.Interpolate('%(prop:artifact.output)s'))
step = ExampleBuildStep("string argument")
You can use Interpolate for that purpose:
util.Interpolate('string before ' + '%(prop:artifact.output)s' + ' string after')
If you have access to the BuildStep object, you can grab properties already formatted as a string via the getProperty() method.
If you wanted to grab the "workername" as a string and print it, you could call:
workerName = step.getProperties().getProperty('workername','wname')
print("workerName: %s" % workerName)
Note: workername is one of the Common Build Properties you should always expect to find, alongside the user-defined ones.
getProperty() is defined in properties.py:
def getProperty(self, name, default=None):
return self.properties.get(name, (default,))[0]
Remember to switch branches from 'master' to whatever your version of buildbot is.

Is there a way to get ad-hoc polymorphism in Python?

Many languages support ad-hoc polymorphism (a.k.a. function overloading) out of the box. However, it seems that Python opted out of it. Still, I can imagine there might be a trick or a library that is able to pull it off in Python. Does anyone know of such a tool?
For example, in Haskell one might use this to generate test data for different types:
-- In some testing library:
class Randomizable a where
genRandom :: a
-- Overload for different types
instance Randomizable String where genRandom = ...
instance Randomizable Int where genRandom = ...
instance Randomizable Bool where genRandom = ...
-- In some client project, we might have a custom type:
instance Randomizable VeryCustomType where genRandom = ...
The beauty of this is that I can extend genRandom for my own custom types without touching the testing library.
How would you achieve something like this in Python?
Python is not a strongly typed language, so it really doesn't matter if yo have an instance of Randomizable or an instance of some other class which has the same methods.
One way to get the appearance of what you want could be this:
types_ = {}
def registerType ( dtype , cls ) :
types_[dtype] = cls
def RandomizableT ( dtype ) :
return types_[dtype]
Firstly, yes, I did define a function with a capital letter, but it's meant to act more like a class. For example:
registerType ( int , TheLibrary.Randomizable )
registerType ( str , MyLibrary.MyStringRandomizable )
Then, later:
type = ... # get whatever type you want to randomize
randomizer = RandomizableT(type) ()
print randomizer.getRandom()
A Python function cannot be automatically specialised based on static compile-time typing. Therefore its result can only depend on its arguments received at run-time and on the global (or local) environment, unless the function itself is modifiable in-place and can carry some state.
Your generic function genRandom takes no arguments besides the typing information. Thus in Python it should at least receive the type as an argument. Since built-in classes cannot be modified, the generic function (instance) implementation for such classes should be somehow supplied through the global environment or included into the function itself.
I've found out that since Python 3.4, there is #functools.singledispatch decorator. However, it works only for functions which receive a type instance (object) as the first argument, so it is not clear how it could be applied in your example. I am also a bit confused by its rationale:
In addition, it is currently a common anti-pattern for Python code to inspect the types of received arguments, in order to decide what to do with the objects.
I understand that anti-pattern is a jargon term for a pattern which is considered undesirable (and does not at all mean the absence of a pattern). The rationale thus claims that inspecting types of arguments is undesirable, and this claim is used to justify introducing a tool that will simplify ... dispatching on the type of an argument. (Incidentally, note that according to PEP 20, "Explicit is better than implicit.")
The "Alternative approaches" section of PEP 443 "Single-dispatch generic functions" however seems worth reading. There are several references to possible solutions, including one to "Five-minute Multimethods in Python" article by Guido van Rossum from 2005.
Does this count for ad hock polymorphism?
class A:
def __init__(self):
pass
def aFunc(self):
print "In A"
class B:
def __init__(self):
pass
def aFunc(self):
print "In B"
f = A()
f.aFunc()
f = B()
f.aFunc()
output
In A
In B
Another version of polymorphism
from module import aName
If two modules use the same interface, you could import either one and use it in your code.
One example of this is from xml.etree.ElementTree import XMLParser

COM objects (arcobjects) in Python

I'm new to OOP and trying to use COM objects (arcobjects) in Python. Program is GIS related, but I did not get any answers on GIS.SE, so I am asking here. Below is piece of my code. I am stuck at the end where I receive iFrameElement. ESRI describe it as member/interface of Abstract Class, which can not create objects itself. I need to pass information contained in it to object in its CoClass (MapFrame).
Any suggestions how to do this?
Also where can I find name conventions for objects in Python? There are p, i as prefix and I am not sure where they come from.
from comtypes.client import CreateObject, GetModule
import arcpy
def CType(obj, interface):
"""Casts obj to interface and returns comtypes POINTER or None"""
try:
newobj = obj.QueryInterface(interface)
return newobj
except:
return None
def NewObj(MyClass, MyInterface):
"""Creates a new comtypes POINTER object where\n\
MyClass is the class to be instantiated,\n\
MyInterface is the interface to be assigned"""
from comtypes.client import CreateObject
try:
ptr = CreateObject(MyClass, interface=MyInterface)
return ptr
except:
return None
esriCarto = GetModule(r"C:\Program Files (x86)\ArcGIS\Desktop10.0\com\esriCarto.olb")
esriCartoUI = GetModule(r"C:\Program Files (x86)\ArcGIS\Desktop10.0\com\esriCartoUI.olb")
esriMapUI = GetModule(r"C:\Program Files (x86)\ArcGIS\Desktop10.0\com\esriArcMapUI.olb")
esriFrame = GetModule(r"C:\Program Files (x86)\ArcGIS\Desktop10.0\com\esriFramework.olb")
arcpy.SetProduct('Arcinfo')
pApp = NewObj(esriFrame.AppROT, esriFrame.IAppROT).Item(0)
pDoc = pApp.Document
pMxDoc = CType(pDoc, esriMapUI.IMxDocument)
pLayout = pMxDoc.PageLayout
pGraphContLayout = CType(pLayout, esriCarto.IGraphicsContainer)
iFrameElement = pGraphContLayout.FindFrame(pMxDoc.ActiveView.FocusMap)
As far as I understand, iFrameElement is an interface of an abstract class from which I need to inherit attributes (pointer) to MapFrame object. How do I do that? How do it get to object with IMapGrids interface? Any suggestions?
IFrameElement is an interface, so you can't create an instance of it per se. This interface is implemented by various classes, including MapFrame, which means (in basic terms) that an instance of any of those objects 'behaves' like an IFrameElement. So if you get an IFrameElement from IGraphicsContainer.FindFrame(), you can pass it to something else that expects an IFrameElement without having to find out what the actual type of the object is.
I would suggest reading up on what Interfaces mean in OOP, because ESRI's code uses them a lot.
On naming convetions - there is no hard & fast rule on what to name your variables.
By the looks of your code, the p refers to an object with a distinct type, and i refers to an object defined only by an interface. But on that note, calling a variable by the same name as the interface it's referencing (except with a lower-case 'i') is a bad way to do things, and will lead to confusion. (IMO)
Edit:
To answer your final question (sorry, I missed it originally):
If pGraphContLayout.FindFrame() returns an object of type MapFrame (and there is no guarantee that it does) then you should be able to simply cast it across to IMapGrids:
pGraphContLayout = CType(pLayout, esriCarto.IGraphicsContainer)
pFrame = pGraphContLayout.FindFrame(pMxDoc.ActiveView.FocusMap)
pGrids = CType(pFrame, IMapGrids)
It sounds like you may be getting confused by Python's abstract base classes, which seem to serve the purpose of interfaces...? This thread is useful: Difference between abstract class and interface in Python

Categories