<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Python &#8211; Digitaldocblog</title>
	<atom:link href="https://digitaldocblog.com/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>https://digitaldocblog.com</link>
	<description>Various digital documentation</description>
	<lastBuildDate>Sat, 13 Aug 2022 16:38:53 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>

<image>
	<url>https://digitaldocblog.com/wp-content/uploads/2022/08/cropped-website-icon-star-500-x-452-transparent-32x32.png</url>
	<title>Python &#8211; Digitaldocblog</title>
	<link>https://digitaldocblog.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Python Classes and Objects in Depth &#8211; A Complete Guide</title>
		<link>https://digitaldocblog.com/python/python-classes-and-objects-in-depth-a-complete-guide/</link>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Thu, 03 Mar 2022 13:00:00 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Object Oriented Programming]]></category>
		<guid isPermaLink="false">https://digitaldocblog.com/?p=147</guid>

					<description><![CDATA[We can think of Classes as blueprints for Objects. Various Object-instances can be created based on one Class blueprint and attributes as well as functionalities defined in the Class blueprint&#8230;]]></description>
										<content:encoded><![CDATA[
<p>We can think of Classes as blueprints for Objects. Various Object-instances can be created based on one Class blueprint and attributes as well as functionalities defined in the Class blueprint will be passed as Object-properties after the Object instance has been created. Classes are callable and whenever we call a Class we create an Object instance of that particular Class. We say that Objects instances will be created based on a certain Class or Objects are of type of a certain Class. </p>



<p>In Classes functions are called methods. The init-method <code>__init__()</code> in a Class is called whenever a Class is called to create an Object instance using <code>Class()</code>. The init-method define attributes, variables and set the Object instance to a defined initial state. Therefore the init-Method is called <em>constructor</em>. </p>



<h3 class="wp-block-heading">The Parameter self</h3>



<p>Let&#8217;s imagine a Class <em>Car</em> that has attributes like brand, color and horsepower. We define the init-method using <code>def __init__(self)</code> and define all attributes using <code>self.&lt;attribut&gt; = &lt;value&gt;</code> in the init-method. A peculiarity of Python is that the init-method has at least one parameter <em>self</em> which is always passed by default. </p>



<p>The parameter <em>self</em> ensure that each attribute and its values will be linked to the correct Object instance stored in a certain memory address space.</p>



<pre class="wp-block-code"><code> class Car:
	def __init__(self):
		self.brand = None
        self.color = None
        self.horsepower = None
	
car1 = Car()
print(car1)

#Print-Output
#&lt;__main__.Car object at 0x10e0ffc40&gt;

</code></pre>



<p>When an Object instance <em>car1</em> of the Class <em>Car</em> will be created using <code>car1 = Car()</code> the init-method within the Class-Definition will be called and the <em>self</em> parameter will be passed to the new Object instance <em>car1</em>. If we print the Object instance <em>car1</em> on the console using <code>print(car1)</code> we don&#8217;t see a list of attributes or something similar, but we see the specific location in memory where the Object instance <em>car1</em> has been stored. This memory address is stored in the <em>self</em> parameter.</p>



<p>To show the peculiarity of Python with the <em>self</em> parameter more clearly, please take a look at the following notation.</p>



<pre class="wp-block-code"><code>class Car:
    def __init__(self):
        self.brand = None
        self.color = None
        self.horsepower = None
        self.self = self #reference is stored in self


car1 = Car()
print(car1)
print(car1.self)
print(car1.brand)

#Print-Output
#&lt;__main__.Car object at 0x10e0ffc40&gt;
#&lt;__main__.Car object at 0x10e0ffc40&gt;
#None

</code></pre>



<p>Within the init-method the value of the <em>self</em> parameter is assigned to the attribute <em>self.self</em> using <code>self.self = self</code>. The output for <code>print(car1.brand)</code> is None as expected. <code>print(car1)</code> and <code>print(car1.self)</code> show exactly the same print output. The memory address ist stored in the parameter <em>self</em> and the Object instance <em>car1</em> is a reference to this memory address. </p>



<h3 class="wp-block-heading">The dot notation</h3>



<p>We can assign values to each attribute, access each value and print the value to the console using the dot notation <code>print(&lt;object-instance&gt;.&lt;attribute-name&gt;)</code>. </p>



<pre class="wp-block-code"><code>class Car:
	def __init__(self):
		self.brand = None
        self.color = None
        self.horsepower = None
        
car1 = Car()
car1.brand = "BMW"
car1.color = "red"
car1.horsepower = 120

car2 = Car()
car2.brand = "Audi"
car2.color = "blue"
car2.horsepower = 150

print(car1.brand)
print(car2.brand)

#Print-Output
#BMW
#Audi

</code></pre>



<p>We create the Object <em>car1</em> as an instance of the Class <em>Car</em>. <em>car1</em> is a BMW, is red, has 120 PS. And we create another Object <em>car2</em>. <em>car2</em> is an Audi, is blue, has 150 PS. <em>car1</em> and <em>car2</em> are Object Instances of the Class <em>Car</em>. It is also often said that <em>car1</em> and <em>car2</em> are Objects of type <em>Car</em>. We access the individual attributes of the objects with the dot notation and get a print output of the brand using <code>print(car1.brand)</code> and <code>print(car2.brand)</code>.</p>



<h3 class="wp-block-heading">Working with Object instances</h3>



<p>To make the code clearer the attribute values ​​can also be passed as parameters directly during object instantiation.</p>



<pre class="wp-block-code"><code>class Car:
	def __init__(self, brand, color, horsepower):
		self.brand = brand
        self.color = color
        self.horsepower = horsepower
        
car1 = Car("BMW", "red", 120)
car2 = Car("Audi", "blue", 150)

print(car1.brand)
print(car2.brand)

#Print-Output
#BMW
#Audi

</code></pre>



<p>Therefore the init-method must have beside the parameter <em>self</em> also the parameters brand, color and horsepower. When we create the Object instances <em>car1</em> and <em>car2</em> of the Class <em>Car</em> we pass the parameters in the brackets during the call of the Class <em>Car</em> .</p>



<p>As mentioned above, functions in Classes are called methods. We have already got to know one method, the init method <code>__init__()</code> that will be executed when an Object instance will be created.</p>



<p>Classes can have also methods designed by the developer himself as well. In our example we add the drive-Method to the Class <em>Car</em> as follows.</p>



<pre class="wp-block-code"><code>class Car:
    def __init__(self, brand, color, horsepower):
        self.brand = brand
        self.color = color
        self.horsepower = horsepower
        self.x = 0
        self.y = 0

    def drive(self):
        self.x += 10
        self.y += 15
		print("X and Y have been increased by 10 and 15")

car1 = Car("BMW", "red", 120)

print(car1.x)
print(car1.y)

car1.drive()

print(car1.x)
print(car1.y)

#Print-Output
#0
#0
#X and Y have been increased by 10 and 15
#10
#15	

</code></pre>



<p>Here we add 2 additional attributes to the constructor <em>self.x</em> and <em>self.y</em> and set both attributes initially to the value 0. The drive-method <code>drive()</code> is defined to increase the values <em>self.x</em> by 10 and <em>self.y</em> by 15 and to print a string to the console. In the above example you can see that the values of <em>self.x</em> and <em>self.y</em> are 0 when we print them to the console directly after the Object <em>car1</em> has been created. Then we call the drive-method on the Object instance <em>car1</em> using <code>car1.drive()</code> and <em>self.x</em> and <em>self.y</em> have been increase by 10 or 15 plus the string has been printed to the console.</p>



<h3 class="wp-block-heading">Inheritance</h3>



<p>There can be several classes in programs, including classes that are very similar and only differ in details. This is where the concept of <em>inheritance</em> comes into play. We want to write a program in which there are 3 classes of vehicles: there are cars, trucks and motorcycles.</p>



<p>We assume all vehicles have the attributes brand, color, and horsepower, but cars should have two drive wheels, trucks four, and motorcycles should have only one drive wheel. In addition, the vehicles have different drive-methods because they can move at different speeds.</p>



<pre class="wp-block-code"><code>class Car:
    def __init__(self, brand, color, horsepower):
        self.brand = brand
        self.color = color
        self.horsepower = horsepower
        self.drivewheels = 2
        self.x = 0
        self.y = 0

    def drive(self):
        self.x += 10
        self.y += 15
        print("Car accelerates by 10 and 15")

class Truck:
    def __init__(self, brand, color, horsepower):
        self.brand = brand
        self.color = color
        self.horsepower = horsepower
        self.drivewheels = 4
        self.x = 0
        self.y = 0

    def drive(self):
        self.x += 5
        self.y += 10
        print("Truck accelerates by 5 and 10")

class Motorcycle:
    def __init__(self, brand, color, horsepower):
        self.brand = brand
        self.color = color
        self.horsepower = horsepower
        self.drivewheels = 1
        self.x = 0
        self.y = 0

    def drive(self):
        self.x += 30
        self.y += 40
        print("Motorcycle accelerates by 30 and 40")

car1 = Car("BMW", "blue", 120)
truck1 = Truck("Volvo", "black", 270)
moto1 = Motorcycle("Yamaha", "green", 70)

print(car1.brand, car1.x, car1.y)
car1.drive()
print(car1.brand, car1.x, car1.y)

print(truck1.brand, truck1.y, truck1.y)
truck1.drive()
print(truck1.brand, truck1.y, truck1.y)

print(moto1.brand, moto1.x, moto1.y)
moto1.drive()
print(moto1.brand, moto1.x, moto1.y)

#Print-Output
#BMW 0 0
#Car accelerates by 10 and 15
#BMW 10 15
#Volvo 0 0
#Truck accelerates by 5 and 10
#Volvo 10 10
#Yamaha 0 0
#Motorcycle accelerates by 30 and 40
#Yamaha 30 40

</code></pre>



<p>We create 3 Object instances from <em>Car</em>, <em>Truck</em> and <em>Motorcycle</em> and have access to their attributes and to their individual drive-methods. Everything is working fine but most of the code is redundant. </p>



<p>Instead of duplicating the code in each Class, we can define a parent Class from which all Child classes inherit their properties. The parent Class in our example will be the Class <em>Vehicle</em>.</p>



<pre class="wp-block-code"><code>class Vehicle:
    def __init__(self, brand, color, horsepower):
        self.brand = brand
        self.color = color
        self.horsepower = horsepower
        self.x = 0
        self.y = 0

	def inheritedmethod(self):
		print("this method was inherited")

class Car(Vehicle):
    drivewheels = 2

    def drive(self):
        self.x += 10
        self.y += 15
        print("Car accelerates by 10 and 15")

class Truck(Vehicle):
    drivewheels = 4

    def drive(self):
        self.x += 5
        self.y += 10
        print("Truck accelerates by 5 and 10")

class Motorcycle(Vehicle):
    drivewheels = 1

    def drive(self):
        self.x += 30
        self.y += 40
        print("Motorcycle accelerates by 30 and 40")


car1 = Car("BMW", "blue", 120)
truck1 = Truck("Volvo", "black", 270)
moto1 = Motorcycle("Yamaha", "green", 70)

print(car1.brand, car1.x, car1.y, car1.drivewheels)
car1.drive()
print(car1.brand, car1.x, car1.y, car1.drivewheels)

print(truck1.brand, truck1.y, truck1.y, truck1.drivewheels)
truck1.drive()
print(truck1.brand, truck1.y, truck1.y, truck1.drivewheels)

print(moto1.brand, moto1.x, moto1.y, moto1.drivewheels)
moto1.drive()
print(moto1.brand, moto1.x, moto1.y, moto1.drivewheels)
moto1.inheritedmethod()

#Print-Output
#BMW 0 0 2
#Car accelerates by 10 and 15
#BMW 10 15 2
#Volvo 0 0 4
#Truck accelerates by 5 and 10
#Volvo 10 10 4
#Yamaha 0 0 1
#Motorcycle accelerates by 30 and 40
#Yamaha 30 40 1
#this method was inherited

</code></pre>



<p>The constructor <code>__init__()</code> of the parent-Class <em>Vehicle</em> contain the initial setup that is inherited to the child-Classes. The parent-Class <em>Vehicle</em> also inherit the method <code>inheritedmethod()</code> to each child-Class. Each Object instance created from a child-Class will have this initial setup. The child-Classes itself have no <code>__init__()</code> constructor in these examples. Each Object instance such as <em>car1</em>, <em>truck1</em> and <em>moto1</em> created from their child-Classes <em>Car</em>, <em>Truck</em> and <em>Motorcycle</em> can access all inherited properties from their common parent-Class <em>Vehicle</em> and their individual Class attributes <code>drivewheels</code> and the individual methods <code>drive()</code>.</p>



<p><strong>note:</strong> <em>I will explain Class-attributes later in the text</em></p>



<p>Inherited methods from the parent-Class can be overwritten in the child-Class.</p>



<pre class="wp-block-code"><code>class Vehicle:
    def __init__(self, brand, color, horsepower):
        self.brand = brand
        self.color = color
        self.horsepower = horsepower
        self.x = 0
        self.y = 0

    def inheritedmethod(self):
        print("this method was inherited")

class Car(Vehicle):
    drivewheels = 2

    def drive(self):
        self.x += 10
        self.y += 15
        print("Car accelerates by 10 and 15")

    def inheritedmethod(self):
        print("this method was inherited and! overwritten")

car1 = Car("BMW", "blue", 120)

print(car1.brand, car1.x, car1.y, car1.drivewheels)
car1.drive()
print(car1.brand, car1.x, car1.y, car1.drivewheels)
car1.inheritedmethod()

#Print-Output
#BMW 0 0 2
#Car accelerates by 10 and 15
#BMW 10 15 2
#this method was inherited and! overwritten

</code></pre>



<p>In order to overwrite an inherited method, the same method head is simply written down again in the child-Class and the code of the method body is then adapted accordingly.</p>



<h3 class="wp-block-heading">The super() method</h3>



<p>A reference to the parent-Class can be established using the <code>super()</code> method. This allows us to take methods from the parent-Class and add additional properties in the code of the method in the child-Class.</p>



<pre class="wp-block-code"><code>class Vehicle:
    def __init__(self, brand, color, horsepower):
        self.brand = brand
        self.color = color
        self.horsepower = horsepower
        self.x = 0
        self.y = 0

    def inheritedmethod(self):
        print("this method was inherited")

class Car(Vehicle):
    def __init__(self, brand, color, horsepower, drivewheels):
        super().__init__(brand, color, horsepower)
        self.drivewheels = drivewheels

    def drive(self):
        self.x += 10
        self.y += 15
        print("Car accelerates by 10 and 15")

    def inheritedmethod(self):
        super().inheritedmethod()
        print("this method was inherited and! overwritten")

class Truck(Vehicle):
    def __init__(self, brand, color, horsepower, drivewheels):
        super().__init__(brand, color, horsepower)
        self.drivewheels = drivewheels

    def drive(self):
        self.x += 5
        self.y += 10
        print("Truck accelerates by 5 and 10")
        
car1 = Car("BMW", "blue", 120, 2)
truck1 = Truck("Magirus Deuz", "grey", 177, 4)

print(car1.brand, car1.x, car1.y, car1.drivewheels)
car1.drive()
print(car1.brand, car1.x, car1.y, car1.drivewheels)
car1.inheritedmethod()

print(truck1.brand, truck1.y, truck1.y, truck1.drivewheels)
truck1.drive()
print(truck1.brand, truck1.y, truck1.y, truck1.drivewheels)
truck1.inheritedmethod()

#Print-Output
#BMW 0 0 2
#Car accelerates by 10 and 15
#BMW 10 15 2
#this method was inherited
#this method was inherited and! overwritten
#Magirus Deuz 0 0 4
#Truck accelerates by 5 and 10
#Magirus Deuz 10 10 4
#this method was inherited

</code></pre>



<p>We had no <code>__init__()</code> method so far in our child-Classes but we defined for each child-Class the specific Class attribute <code>drivewheels</code>. This approach works fine. To understand how the <code>super()</code> method works we code for each child-Class a specific <code>__init__()</code> method and provide all parameters plus the parameter <code>drivewheels</code>. This means the value for <code>drivewheels</code> will be passed when the Object-instance from the child-Class is created and we have more flexibility there. Finally, it is possible that cars for example can have 4 drive wheels instead of 2. Then we use the <code>super()</code> method to refer to the <code>__init__()</code> method in the parent-Class and  pass the properties required there and create the additional property <code>self.drivewheels = drivewheels</code> . In the child-Class <em>Car</em> we also use the <code>super()</code> method in the method <code>inheritedmethod</code> and add additional functionality (simple print command). We don’t do this in the child-Class Truck. Then we create the Object instances <em>car1</em> and <em>truck1</em> and access the properties and methods.</p>



<h3 class="wp-block-heading">Special attributes</h3>



<p>The attributes used so far are all 100 percent usable outside of the respective class definition. In the code below I have simplified the classes considerably to focus on the essentials. </p>



<pre class="wp-block-code"><code>class Vehicle:
    def __init__(self, brand, color, horsepower):
        self.brand = brand
        self.color = color
        self.horsepower = horsepower

class Car(Vehicle):
    def __init__(self, brand, color, horsepower, drivewheels):
        super().__init__(brand, color, horsepower)
        self.drivewheels = drivewheels

car1 = Car("BMW", "blue", 120, 2)

print(car1.brand)
car1.brand = "Audi"
print(car1.brand)

#Print-Output
#BMW
#Audi

</code></pre>



<p>We access the attribute <em>brand</em> and print the value <em>BMW</em> to the console. Then we change the value from <em>BMW</em> to <em>Audi</em> using the dot notation and overwrite the existing value. </p>



<p>Sometimes developers of a Class want to signal developers that attributes should only be used inside the Class and not outside. Developers can mark attributes with one underscore <code>_</code> or with two underscores <code>__</code> to show that attributes should not or can not be easily overridden.</p>



<pre class="wp-block-code"><code>class Vehicle:
    def __init__(self, brand, color, vmax):
        self._brand = brand
        self.__color = color
        self.vmax = vmax

class Car(Vehicle):
    def __init__(self, brand, color, vmax, drivewheels):
        super().__init__(brand, color, vmax)
        self.drivewheels = drivewheels

car1 = Car("BMW", "blue", 100, 2)

print(car1._brand)
car1._brand = "Audi"
print(car1._brand)

print(car1._Vehicle__color)
car1._Vehicle__color = "black"
print(car1._Vehicle__color)

#Print-Output
#BMW
#Audi
#blue
#black

</code></pre>



<p>In the example above we have the attribute <code>_brand</code> with one underscore. This shows the developer that <code>_brand</code> is a special attribute which is defined in the parent-Class <em>Vehicle</em> and inherited to the child-Class <em>Car</em> and should not be overwritten. However, overwriting is possible without any problems using the dot notation. The attribute <code>__color</code> is also defined in parent-Class <em>Vehicle</em> and inherited to child-Class <em>Car</em> but can not be overwritten using the standard dot notation. The value of the attribute <code>__color</code> can only be accessed using a different attribute name <code>_Vehicle__color</code>. Obviously the name of the attribute <code>__color</code> can only be accessed if we extend the attribute name at the beginning with <code>&lt;_parent-Classname&gt;&lt;__attribute-name&gt;.</code> This is called <em>Name Mangling</em>.</p>



<h3 class="wp-block-heading">Multiple inheritance</h3>



<p>So far we had a parent-Class and single inheritance of properties to a child-Class. But it is also possible to define more parent-Classes and inherit their properties to a child-Class. This is called <em>multiple inheritance</em>. With multiple inheritance we can create complex data structures. In the following code I define 3 parent-Classes <em>Person</em>, <em>Organisation</em>, <em>Building</em> and 2 child-Classes <em>Employee</em> and <em>Location</em>. </p>



<pre class="wp-block-code"><code>class Person:
    def __init__(self, userid, name, lastname, age):
        self.userid = userid
        self.name = name
        self.lastname = lastname
        self.age = age

class Organisation:
    def __init__(self, company, orgunit):
        self.company = company
        self.orgunit = orgunit

class Building:
    def __init__(self, country, postalcode, street, city):
        self.country = country
        self.postalcode = postalcode
        self.street = street
        self.city = city

class Employee(Person, Organisation):
    def __init__(self, userid, name, lastname, age, company, orgunit):
        Person.__init__(self, userid, name, lastname, age)
        Organisation.__init__(self,  company, orgunit)

class Location(Building, Organisation):
    def __init__(self, country, postalcode, street, city, company, orgunit):
        Building.__init__(self, country, postalcode, street, city)
        Organisation.__init__(self, company, orgunit)


employee1 = Employee("12345", "Parick", "Rottländer", 54, "Company 1", "OE123456")
employee2 = Employee("67890", "Carol", "Meier", 32, "Company 2", "OE678901")
location1 = Location("Germany", "81234", "First Street 20", "Munich", "Company 1", "OE123456")
location2 = Location("Italy", "I23345", "Second Street 100", "Verona", "Company 2", "OE678901")

print(employee1.name, employee1.orgunit)
print(employee2.name, employee2.orgunit)
print(location1.country, location1.city)
print(location2.country, location2.city)

#Print-Output
#Parick OE123456
#Carol OE678901
#Germany Munich
#Italy Verona

</code></pre>



<p>In the code example above we define the child-Class <em>Employee</em> with properties from the parent-Classes <em>Person</em> and <em>Organisation</em>. Child-Class <em>Building</em> is defined with properties from parent-Classes <em>Location</em> and <em>Organisation</em>. Therefore the child-Class <em>Employee</em> inherits properties from parent-Classes <em>Person</em> and <em>Organization</em> and the child-Class <em>Location</em> inherit properties from parent-Classes <em>Building</em> and <em>Organisation</em>. In each child-Class the first <code>__init__()</code> constructor define the complete setup of an Object instance. Then each inherited parent-Class <code>__init()__</code> constructor is overwritten using the dot notation <code>&lt;parent-Class&gt;.__init()__</code>. Then we create the object instances <em>employee1</em>, <em>employee2</em> and <em>location1</em> and <em>location2</em> passing all required attributes and have access to each of those attributes using the dot notation. </p>



<h3 class="wp-block-heading">Instance- and Class-attributes</h3>



<p>If attributes of a Class are defined within the <code>__init()__</code> method, these are <em>Instance-attributes</em> and are available as initial setup in each Object instance created from that Class. If we define attributes in a Class before the <code>__init()__</code> method then these are <em>Class-attributes</em>. </p>



<pre class="wp-block-code"><code>class Person:
    counter = 0
    def __init__(self, name, lastname, age):
        self.userid = "P" +"-" +str(Person.counter)
        self.name = name
        self.lastname = lastname
        self.age = age
        Person.counter += 1

class Organisation:
    def __init__(self, company, orgunit):
        self.company = company
        self.orgunit = orgunit

class Employee(Person, Organisation):
    def __init__(self, name, lastname, age, company, orgunit):
        Person.__init__(self, name, lastname, age)
        Organisation.__init__(self,  company, orgunit)

print(Person.counter)
employee1 = Employee("Parick", "Rottländer", 54, "Company 1", "OE123456")
print(employee1.userid)
print(Person.counter)
employee2 = Employee("Carol", "Meier", 32, "Company 2", "OE678901")
print(employee2.userid)
print(Person.counter)

#Print-Output
#0
#P-0
#1
#P-1
#2
</code></pre>



<p>In the Class <em>Person</em> I define the Class-attribute <em>counter</em> and set its value to 0. Within the <code>__init__()</code> method of the Class <em>Person</em> I access the Class-attribute <em>counter</em> using <code>str(Person.counter)</code> to create a unique userid. Whenever an Object instance of <em>Person</em> is created <code>Person.counter</code> increase by 1 (see the respective print-output).</p>



<h3 class="wp-block-heading">Modules</h3>



<p>In the examples above we write the code in one Python file with the ending <code>&lt;filename&gt;.py</code>. Each Python file is a Module itself and can be executed independently. But a developer must not code any method on his own he or she can use existing code from third parties by loading other modules into his Python file. After modules have been loaded methods and properties defined in those modules can be user in the code.</p>



<p>Python has numerous <a href="https://docs.python.org/3/py-modindex.html" title="Build-in Modules in Python">built-in modules</a>. All of them can be used for free by developers in the code. In the following examples I will use the build-in module <a href="https://docs.python.org/3/library/math.html" title="Math Build-in Python Module">math</a> because math contain the parameter <em>pi </em> that we need for the calculation of the area of a circle for a given radius.  </p>



<pre class="wp-block-code"><code>#objectMain.py

import math

class Circle:
    def __init__(self, radius):
        self.radius = radius

    #calculate area from given radius
    def area(self):
        return math.pi * self.radius ** 2

c1 = Circle(5)
print(c1.area())

#Print-Output
#78.53981633974483

</code></pre>



<p>In the file <code>objectMain.py</code> we first <code>import math</code> and define the Class <em>Circle</em>. Then we pass the parameter <em>radius</em> in the <code>__init()__</code> constructor. The instance attribute <em>self.radius</em> receive the given value <em>radius</em> when an Object instance is created with a given radius value. The <code>area()</code>method use the parameter <em>pi</em> from the math Module and return the calculated area for the given radius.  </p>



<p>But we can also develop methods on our own separately in separate Python files and make them available as modules. We can then either import the entire module or just individual methods from the module. I define a method <code>radius()</code> in a separate module <code>objectModuleCalc.py</code> to calculate the radius from a given area. </p>



<pre class="wp-block-code"><code>#objectModuleCalc.py

import math

#calculate radius from given area
def radius(area):
    return math.sqrt(area/math.pi)

</code></pre>



<p>To use the method <code>radius()</code> in my  <code>objectMain.py</code> file I must import the module from the <code>objectModuleCalc.py</code> file using <code>import &lt;filename&gt;</code>. </p>



<pre class="wp-block-code"><code>#objectMain.py

import math
import objectModuleCalc

class Circle:
    def __init__(self, radius):
        self.radius = radius

    #calculate area from given radius
    def area(self):
        return math.pi * self.radius ** 2

c1 = Circle(5)
print(c1.area())

print(objectModuleCalc.radius(78.54))

#Print-Output
#78.53981633974483
#5.000005846084075

</code></pre>



<p>After the import I can access the method <code>radius()</code> in the imported module using the dot notation<code>&lt;filename&gt;.&lt;method&gt;</code>. </p>



<p>Another way to import the Module from the <code>objectModuleCalc.py</code> file is using an alias <code>import &lt;filename&gt; as &lt;alias&gt;</code>. </p>



<pre class="wp-block-code"><code>#objectMain.py

import math
import objectModuleCalc as calc

class Circle:
    def __init__(self, radius):
        self.radius = radius

    #calculate area from given radius
    def area(self):
        return math.pi * self.radius ** 2

c1 = Circle(5)
print(c1.area())

print(calc.radius(78.54))

#Print-Output
#78.53981633974483
#5.000005846084075

</code></pre>



<p>After the import I can access the code in the imported module using the dot notation<code>&lt;alias&gt;.&lt;method&gt;</code>.</p>



<p>In the example above you see that the method <code>area()</code> can only be used when an object instance has been created. The method is used on the Object instance using <code>c1.area()</code>. </p>



<h3 class="wp-block-heading">Static Methods</h3>



<p>With <em>static methods</em> we can use a method defined in a class without having created an Object instance. We have no Class reference and no Object reference. We use the Function Decorator <code>@staticmathod</code> before the method definition.  </p>



<pre class="wp-block-code"><code>#objectMain.py

import math

class Circle:
    def __init__(self, radius):
        self.radius = radius

    #calculate area from given radius
    @staticmethod
    def area(radius):
        return math.pi * radius ** 2

print(Circle.area(5))

#Print-Output
#78.53981633974483

</code></pre>



<p>Static methods have no reference to the Class and no reference to the Object instance once it has been created. Therefore we can not access any attributes defined in the Class like Class-attributes or the Instance-attribute <code>self.radius</code>. This is the reason why we must pass a separate parameter <code>radius</code> into the method <code>area()</code>. The value of the parameter <em>radius</em> can then be used by the variable <em>radius</em> within the method <code>area()</code> when we call the method using <code>&lt;Classname&gt;.&lt;method&gt;(&lt;parameter&gt;)</code>. </p>



<h3 class="wp-block-heading">Class methods</h3>



<p>With <em>Class methods</em> we can use a method defined in a Class also without having created an Object instance. We use the Function Decorator <code>@classmethod</code> before the method definition. </p>



<pre class="wp-block-code"><code>#objectMain.py

import math

class Circle:
    counter = 0
    def __init__(self, radius):
        self.radius = radius
        Circle.counter += 1

    #calculate area from given radius
    @staticmethod
    def area(radius):
        return math.pi * radius ** 2

    #print the current counter value
    @classmethod
    def printcounter(cls):
        print("Actual value of counter is: " +str(cls.counter))

Circle.printcounter()
c1 = Circle(5)
Circle.printcounter()

#Print-Output
#Actual value of counter is: 0
#Actual value of counter is: 1

</code></pre>



<p>I define the Class method <code>printcounter(cls)</code>. The parameter <em>cls</em> is the Class reference to ensure that also Class-attributes like <em>counter</em> can be used within the Class-method. The Class-method is called using <code>&lt;Classname&gt;.&lt;class-method-name&gt;</code>. In the Class <em>Circle</em> we define the Class-attribute <em>counter</em> ant set it to the value of 0. The <code>__init__()</code> constructor create an Object instance of type <em>Circle</em> when we call <code>Circle()</code> . Each time we create an Object instance, the counter value of the Class <em>Circle</em> is incremented by 1. We define the Class-method <code>printcounter(cls)</code> and pass the parameter <em>cls</em> to establish the Class reference. Then we can access the Class attribute counter in the <code>printcounter(cls)</code> method using <code>cls.counter</code>. We call the Class method using <code>&lt;Classname&gt;.&lt;classmethod&gt;</code> and see in the print output that the counter value increased by 1 after we created the Object instance <em>c1</em>.</p>



<p><strong>note:</strong> <em>In the <code>__init__()</code> constructor above we still use the parameter <code>radius</code> and we pass a value for <code>radius</code> when we create an Object instance from Class Circle. This does not really make sense in this example because we do not use it as we the method <code>area()</code> is defined as static method and there we pass a separate radius value with the method call. Because we will need passing the radius in the text below I decided to keep the <code>__init__()</code> constructor as it is to avoid confusion.</em> </p>



<p>The Class method <code>printcounter(cls)</code> above return a <code>print()</code> function. So when we call the method  <code>printcounter(cls)</code> we get a print output at the console. </p>



<p>A Class-method can also return an Object instance. Therefore I define another Class-method <code>radius(cls, area)</code> in the code below. This Class-method has 2 parameters: <em>cls</em> is the Class parameter and stand for the Class reference to ensure that also Class-attributes can be used within the Class method and <em>area</em> to pass the given area value to calculate the radius.</p>



<pre class="wp-block-code"><code>#objectMain.py

import math

class Circle:
    counter = 0
    def __init__(self, radius):
        self.radius = radius
        Circle.counter += 1

    #calculate area from given radius
    @staticmethod
    def area(radius):
        return math.pi * radius ** 2

    #print the current counter value
    @classmethod
    def printcounter(cls):
        print("Actual value of counter is: " +str(cls.counter))

    #calculate radius from given area
    @classmethod
    def radius(cls, area):
        r = math.sqrt(area / math.pi)
        return Circle(r)

Circle.printcounter()
c1 = Circle(5)
print(type(c1))
print(c1.radius)
Circle.printcounter()
c2 = Circle.radius(78)
print(type(c2))
print(c2.radius)
Circle.printcounter()

#Print-Output
#Actual value of counter is: 0
#&lt;class '__main__.Circle'&gt;
#5
#Actual value of counter is: 1
#&lt;class '__main__.Circle'&gt;
#4.982787485166879
#Actual value of counter is: 2

</code></pre>



<p>The Class method <code>radius()</code>here is the same method we defined above in a separate module. Here we use <code>radius()</code> to calculate the radius <em>r</em> for a given area value that we pass with the method call. The Class method <code>radius()</code>  return an Object instance of type <em>Circle</em> passing the calculated radius using <code>return Circle(r)</code>. After we create the Object instance <em>c1</em> using <code>c1 = Circle(5)</code> we see in the print output above that <em>c1</em>  is of type <em>Circle</em> <code>class '__main__.Circle </code>.  We can access the passed radius value using the dot notation <code>c1.radius</code>. Then we call the Class-method <code>Circle.radius(cls, area)</code> with the area parameter 78 and assign the return value to the variable <em>c2</em> using <code>c2 = Circle.radius(78)</code>. As we expected <em>c2</em> is also of type <code>class '__main__.Circle </code> . We can access the calculated radius value using <code>c2.radius</code>. In the print output you also see that the counter increased from 0 to 2 meaning that 2 Object instances <em>c1</em> and <em>c2</em> both of type <em>Circle</em> have been created. </p>



<p>A Class-method can return an Object instance of type of the calling class. Therefore I define a new child-Class <em>Rim</em>. <em>Rim</em> inherits all properties of the parent-Class <em>Circle</em> using <code>Rim(Circle)</code> and <em>Rim</em> has no <code>__init__()</code> constructor. Instead we use <em>pass</em> so that we can create an Object instance of <em>Rim</em> and all properties come from the parent-Class <em>Circle</em>. </p>



<pre class="wp-block-code"><code>#objectMain.py

import math

class Circle:
    counter = 0
    def __init__(self, radius):
        self.radius = radius
        Circle.counter += 1

    #calculate area from given radius
    @staticmethod
    def area(radius):
        return math.pi * radius ** 2

    #print the current counter value
    @classmethod
    def printcounter(cls):
        print("Actual value of counter is: " +str(cls.counter))

    #calculate radius from given area
    @classmethod
    def radius(cls, area):
        r = math.sqrt(area / math.pi)
        return cls(r)

class Rim(Circle):
    pass

Circle.printcounter()
c2 = Circle.radius(78)
print(type(c2))
print(c2.radius)

Circle.printcounter()
r1 = Rim.radius(120)
print(type(r1))
print(r1.radius)

Circle.printcounter()

#Print-Output
#Actual value of counter is: 0
#&lt;class '__main__.Circle'&gt;
#4.982787485166879
#Actual value of counter is: 1
#&lt;class '__main__.Rim'&gt;
#6.180387232371033
#Actual value of counter is: 2

</code></pre>



<p>The Class method <code>radius()</code> in the parent-Class <em>Circle</em> has changed a bit: The method return not necessarily an Object instance of type <em>Circle</em> but an Object instance of the calling Class <code>return cls(r)</code>.  Then we call the Class method <code>Circle.radius(cls, area)</code> with the area parameter 78 and assign the return value to the variable <em>c2</em> using <code>c2 = Circle.radius(78)</code>. As expected <em>c2</em> is of type <code>class '__main__.Circle </code> . When we call the Class method using <code>Rim.radius(cls, area)</code> with the area parameter 120 and assign the return value to the variable <em>r1</em> using <code>r1 = Rim.radius(120)</code> we see that <em>r1</em> is of type <code>class '__main__.Rim </code>.</p>



<h3 class="wp-block-heading">Property attributes and setters</h3>



<p>In the text above we have already dealt with attributes that begin with one underscore <code>_</code> or double underscores <code>__</code> and thus indicate that these attributes should be touched carefully from the outside or even cannot be changed at all in the case when we use double underscores. </p>



<p>Here we want to deal again with accessing attributes and changing their values. To show the problem I use the Class Circle and the method <code>area()</code> that is defined within the Class <em>Circle</em> to calculate the area value for the given radius that we pass when we create an Object instance <em>c1</em>using <code>c1 = Circle(&lt;radius&gt;)</code>.</p>



<pre class="wp-block-code"><code>import math

class Circle:
    def __init__(self, radius):
        self.radius = radius

    # calculate area from given radius
    def area(self):
        return math.pi * self.radius ** 2

c1 = Circle(5)
print(c1.radius)
print(c1.area())
c1.radius = -10
print(c1.radius)

#Print-Output
#5
#78.53981633974483
#-10
#print(c1.area())
#314.1592653589793

</code></pre>



<p>In the code above you see that we are able to change the value of radius from outside to <em>-10</em> using <code>c1.radius = -10</code>. This doesn&#8217;t make much sense, even if the value of the area is calculated correctly because <code>self.radius ** 2</code> in the <code>area()</code> method.</p>



<p>Then we define the instance attribute <code>self._radius</code> in the <code>__init__()</code> constructor. The radius value passed when we create the Object instance will be assigned to <code>self_radius</code> using <code>self_radius = radius</code> . The underscore shows that the attribute should be touched carefully from the outside.</p>



<pre class="wp-block-code"><code>import math

class Circle:
    def __init__(self, radius):
        self._radius = radius

    # calculate area from given radius
    def area(self):
        return math.pi * self._radius ** 2

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, radius):
        if radius &gt;= 0:
            self._radius = radius

c1 = Circle(5)

print(c1.radius)
print(c1.area())

c1.radius = -10
print(c1.radius)
print(c1.area())

c1.radius = 10
print(c1.radius)
print(c1.area())

c1._radius = -10
print(c1.radius)
print(c1.area())

#Print-Output
#5
#78.53981633974483
#5
#78.53981633974483
#10
#314.1592653589793
#-10
#314.1592653589793

</code></pre>



<p>First we define a Property attribute using the Property Decorator <code>@Property</code>. The Property attribute definition is a method that return <code>self_radius</code> when we call <code>radius</code>. This mean when we can call <code>&lt;Object-Instance&gt;.radius</code> instead of <code>&lt;Object-Instance&gt;._radius</code> when we want to access the Property attribute. Then we define a Property setter using <code>@&lt;Property-attribute&gt;.setter</code>, in this case we use <code>@radius.setter</code>. The Property setter definition is a method that set <code>self._radius = radius</code> only in case radius is greater or equal to 0. In the following we create the Object instance <em>c1</em>  with given radius of 5 and access the given radius using <code>c1.radius</code>. As you see in the print output we are able to change the value to <em>10</em>. Even if we are not able to change the value to <em>-10</em> when we use <code>c1.radius = -10</code> we are still able to change the value to <em>-10</em> using <code>c1._radius = -10</code>.</p>



<p>We define the instance attribute <code>self.__radius</code> in the <code>__init__()</code> constructor. The radius value passed when we create the Object instance will be assigned to <code>self__radius</code> using <code>self__radius = radius</code>. The double underscore <code>__</code> shows that the attribute can not be touched from the outside.</p>



<pre class="wp-block-code"><code>class Circle:
    def __init__(self, radius):
        self.__radius = radius

    # calculate area from given radius
    def area(self):
        return math.pi * self.__radius ** 2

    @property
    def radius(self):
        return self.__radius

    @radius.setter
    def radius(self, radius):
        if radius &gt;= 0:
            self.__radius = radius

c1 = Circle(5)
print(c1.radius)
print(c1.area())

c1.radius = -10
print(c1.radius)
print(c1.area())

c1.radius = 10
print(c1.radius)
print(c1.area())

c1.__radius = -10
print(c1.radius)
print(c1.area())

#Print-Output
#5
#78.53981633974483
#5
#78.53981633974483
#10
#314.1592653589793
#10
#314.1592653589793

</code></pre>



<p>The Property attribute definition is a method that now return <code>self__radius</code> when we call <code>radius</code>. The Property setter definition is now a method that set <code>self.__radius = radius</code> only in case radius is greater or equal to 0. We create the Object instance <em>c1</em>  with given radius of 5 and access the given radius using <code>c1.radius</code>. As you see in the print output we are able to change the value to <em>10</em> but we are not able to change the value to <em>-10</em> when we use <code>c1.radius = -10</code> and <code>c1.__radius = -10</code>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Python on MacOS BigSur</title>
		<link>https://digitaldocblog.com/mac/python-on-macos-bigsur/</link>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Wed, 20 Oct 2021 12:00:00 +0000</pubDate>
				<category><![CDATA[Mac OS]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://digitaldocblog.com/?p=144</guid>

					<description><![CDATA[MacOS comes with Python 2 pre-installed. Python 2 is required by the Operating System and managed by MacOS. This System Python should never be touched. System Python is installed in&#8230;]]></description>
										<content:encoded><![CDATA[
<p>MacOS comes with Python 2 pre-installed. Python 2 is required by the Operating System and managed by MacOS. This <em>System Python</em> should <strong>never be touched</strong>.   </p>



<p>System Python is installed in <em>/usr/bin</em> directory which is owned by <em>root</em>. This mean all files and symlinks in <em>/usr/bin</em> are system owned which means managed by the system and not managed by the user. In <em>/usr/bin</em> you find python symlinks pointing to the Python binaries in <em>/System/Library/Frameworks/Python.framework/Versions/2.7/bin</em> directory. </p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % ls -l /usr/bin/python* 

lrwxr-xr-x  1 root  wheel      75  1 Jan  2020 /usr/bin/python -&gt; ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7

lrwxr-xr-x  1 root  wheel      75  1 Jan  2020 /usr/bin/python2 -&gt; ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7

lrwxr-xr-x  1 root  wheel      75  1 Jan  2020 /usr/bin/python2.7 -&gt; ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7

....

patrick@PatrickMBNeu ~ %
</code></pre>



<p>The symlinks python, python2 and python2.7 in <em>/usr/bin</em> each point to the same binary in <em>/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7</em>. So when you type one of these as shell command in your shell terminal the binary in <em>/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7</em> will be executed.  </p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % python --version
Python 2.7.16

patrick@PatrickMBNeu ~ % python2 --version
Python 2.7.16

patrick@PatrickMBNeu ~ % python2.7 --version
Python 2.7.16

patrick@PatrickMBNeu
</code></pre>



<p>Type in the command without using the path like <em>/usr/bin/python</em> works because <em>/usr/bin</em> is configured in the shell PATH variable. </p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

patrick@PatrickMBNeu ~ %  
</code></pre>



<p>The shell lookup for a command in the paths defined in the PATH variable and starts on the left side of the PATH. So python, python2 and python2.7 do not exist in <em>/usr/local/bin</em> but in <em>/usr/bin</em>. </p>



<p>When you came from Catalina and upgraded to BigSur you realized that System Python has not been upgraded from Python 2 to Python 3 for example. So obviously BigSur still relies on Python 2 which is ok for your Mac but maybe not for you as a Developer. You might need newer or different versions of Python on your system. You must install this them separately. </p>



<p>Many people use <em><a href="https://brew.sh/">Homebrew</a></em> to install software packages on their MacOS. Homebrew can also be used to install a Python version in addition to the System Python. You can check if Python is installed via Homebrew on your system using the command <em>brew info &lt;formula&gt;</em>. </p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % brew info python
python@3.9: stable 3.9.7 (bottled)
Interpreted, interactive, object-oriented programming language
https:&#47;&#47;www.python.org/
/usr/local/Cellar/python@3.9/3.9.7_1 (3,191 files, 56MB) *
  Poured from bottle on 2021-10-15 at 07:09:27
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/python@3.9.rb
License: Python-2.0
==&gt; Dependencies
Build: pkg-config &#x2714;
Required: gdbm &#x2714;, mpdecimal &#x2714;, openssl@1.1 &#x2714;, readline &#x2714;, sqlite &#x2714;, xz &#x2714;
==&gt; Caveats
Python has been installed as
  /usr/local/bin/python3

Unversioned symlinks `python`, `python-config`, `pip` etc. pointing to
`python3`, `python3-config`, `pip3` etc., respectively, have been installed into
  /usr/local/opt/python@3.9/libexec/bin

You can install Python packages with
  pip3 install &lt;package&gt;
They will install into the site-package directory
  /usr/local/lib/python3.9/site-packages

tkinter is no longer included with this formula, but it is available separately:
  brew install python-tk@3.9

See: https://docs.brew.sh/Homebrew-and-Python
==&gt; Analytics
install: 717,857 (30 days), 1,988,212 (90 days), 8,421,529 (365 days)
install-on-request: 322,364 (30 days), 784,390 (90 days), 2,811,664 (365 days)
build-error: 0 (30 days)

patrick@PatrickMBNeu ~ %
</code></pre>



<p>Here on my system Python has been installed with Homebrew in the directory <em>/usr/local/bin</em> which is owned by the user. That means all files and symlinks in this directory can be managed by the user. In <em>/usr/local/bin</em> you find the python symlinks python3 and python3.9 pointing to further symlinks in the Homebrew Cellar in <em>/usr/local/Cellar</em>. </p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % ls -l /usr/local/bin/python*

lrwxr-xr-x  1 patrick  admin  40 15 Okt 07:09 /usr/local/bin/python3 -&gt; ../Cellar/python@3.9/3.9.7_1/bin/python3

lrwxr-xr-x  1 patrick  admin  42 15 Okt 07:09 /usr/local/bin/python3.9 -&gt; ../Cellar/python@3.9/3.9.7_1/bin/python3.9

...

patrick@PatrickMBNeu ~ %
</code></pre>



<p>The python3 symlink in the Homebrew Cellar point again to another python3 symlink in <em>/usr/local/Frameworks/Python.framework/Versions/3.9/bin</em> and this symlink point finally to python3.9 binary <em>/usr/local/Frameworks/Python.framework/Versions/3.9/bin</em>. The python3.9 symlink from the Homebrew Cellar point directly to the python3.9 binary in <em>/usr/local/Frameworks/Python.framework/Versions/3.9/bin</em>. </p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % ls -l /usr/local/Frameworks/Python.framework/Versions/3.9/bin
total 136

lrwxr-xr-x  1 patrick  admin      9 30 Aug 21:19 python3 -&gt; python3.9

-rwxr-xr-x  1 patrick  admin  50472 15 Okt 07:09 python3.9

...

patrick@PatrickMBNeu ~ % 
</code></pre>



<p>So If you enter python3 or python3.9 as a command in the terminal the shell lookup these symlinks in directory <em>/usr/local/bin</em> and find a match. In any case you always end up with the python3.9 binary in <em>/usr/local/Frameworks/Python.framework/Versions/3.9/bin</em> and execute the same binary.</p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % python3 --version
Python 3.9.7

patrick@PatrickMBNeu ~ % python3.9 --version
Python 3.9.7

patrick@PatrickMBNeu ~ %
</code></pre>



<p>It is not a problem to install other Python versions with Homebrew in addition to the System Python, but the Homebrew ecosystem has a special feature: dependencies. Python versions that are installed in the Homebrew perimeter can also represent a dependency on other applications. node, for example, needs Python 3.9. If we uninstall Python 3.9, we have a problem with node. Therefore, Python can never be seen completely isolated in the Homebrew ecosystem and this is exactly the problem we solve with <a href="https://github.com/pyenv/pyenv">pyenv</a>.</p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % brew info node   
                                                 
node: stable 16.11.1 (bottled), HEAD
Platform built on V8 to build network applications
https:&#47;&#47;nodejs.org/
/usr/local/Cellar/node/16.11.1 (1,980 files, 45.4MB) *
  Poured from bottle on 2021-10-15 at 07:09:45
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/node.rb
License: MIT
==&gt; Dependencies
Build: pkg-config &#x2714;
Required: brotli &#x2714;, c-ares &#x2714;, icu4c &#x2714;, libnghttp2 &#x2714;, libuv &#x2714;, openssl@1.1 &#x2714;, python@3.9 &#x2714;
==&gt; Options
--HEAD
	Install HEAD version
==&gt; Analytics
install: 501,912 (30 days), 1,345,537 (90 days), 4,731,822 (365 days)
install-on-request: 404,509 (30 days), 1,070,393 (90 days), 3,650,272 (365 days)
build-error: 0 (30 days)

patrick@PatrickMBNeu ~ %
</code></pre>



<p>pyenv create a complete isolated environment for your Python versions. You are able to install, use and uninstall Python versions and you can switch between them.  pyenv can be easily installed with Homebrew. pyenv is therefore installed in the <em>/usr/local/bin</em> directory.</p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % which pyenv
/usr/local/bin/pyenv

patrick@PatrickMBNeu ~ % pyenv --version
pyenv 2.1.0

patrick@PatrickMBNeu ~ % 
</code></pre>



<p>We must adapt the PATH variable for the standard shell. Here in my example this is configured in the .zshrc file in my Home-Directory. </p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % cat .zshrc

# ~/.pyenv provides Python before others of the same name
export PYENV_ROOT=$(pyenv root)
export PATH="$PYENV_ROOT/shims:$PATH"

patrick@PatrickMBNeu ~ %
</code></pre>



<p>You check the versions managed by pyenv with the following command. As you see pyenv realize the System Python. With the command <em>pyenv install 3.9.7</em> you install Python 3.9.7 in your pyenv environment. You can switch to your desired Python version using the command <em>pyenv global &lt;version&gt;</em> .</p>



<p>When you then run the command <em>python</em> you are directly connected to global python version you selected. </p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % pyenv versions 
*  system

patrick@PatrickMBNeu ~ % pyenv install 3.9.7

.....

patrick@PatrickMBNeu ~ % pyenv versions 
* system
  3.9.7 (set by /Users/patrick/.pyenv/version)

patrick@PatrickMBNeu ~ % pyenv global 3.9.7

patrick@PatrickMBNeu ~ % pyenv versions 
  system
* 3.9.7 (set by /Users/patrick/.pyenv/version)

patrick@PatrickMBNeu ~ % python
Python 3.9.7 (default, Oct 19 2021, 16:02:07) 
&#91;Clang 13.0.0 (clang-1300.0.29.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; exit()

patrick@PatrickMBNeu ~ % pyenv global system

patrick@PatrickMBNeu ~ % pyenv versions     
* system (set by /Users/patrick/.pyenv/version)
  3.9.7

patrick@PatrickMBNeu ~ % python             

WARNING: Python 2.7 is not recommended. 
This version is included in macOS for compatibility with legacy software. 
Future versions of macOS will not include Python 2.7. 
Instead, it is recommended that you transition to using 'python3' from within Terminal.

Python 2.7.16 (default, Aug 30 2021, 14:43:11) 
&#91;GCC Apple LLVM 12.0.5 (clang-1205.0.19.59.6) &#91;+internal-os, ptrauth-isa=deploy on darwin
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; exit()

patrick@PatrickMBNeu ~ %
</code></pre>



<p>Finally: To avoid a warning message from brew when you run <em>brew doctor</em> you must create a brew alias in your .zshrc file. </p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % cat .zshrc

alias brew='PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin brew'

# ~/.pyenv provides Python before others of the same name
export PYENV_ROOT=$(pyenv root)
export PATH="$PYENV_ROOT/shims:$PATH"

patrick@PatrickMBNeu ~ %
</code></pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to manage different Python Versions on Mac OS 11 Big Sur</title>
		<link>https://digitaldocblog.com/mac/how-to-manage-different-python-versions-on-mac-os-11-big-sur/</link>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Sat, 13 Mar 2021 12:00:00 +0000</pubDate>
				<category><![CDATA[Mac OS]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://digitaldocblog.com/?p=127</guid>

					<description><![CDATA[Before you go on reading this article ensure that Homebrew is installed on your Mac. There are installation instructions on my blog digitaldocblog.com or you can just go to the&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Before you go on reading this article ensure that <a href="https://brew.sh/">Homebrew</a> is installed on your Mac. There are installation instructions on my blog <a href="https://digitaldocblog.com/singleblog?article=0">digitaldocblog.com</a> or you can just go to the <a href="https://brew.sh/">Homebrew website</a> and follow the instructions there.</p>



<p>But first of all I would like to describe my initial situation. I think some Mac users have python installed on their mac by themselves in one way or another and are surprised when checking the current version with <code>python -V</code> or when checking which python binary is currently being executed with the command <code>which python</code>.  I installed python 2 and 3 with <a href="https://brew.sh/">Homebrew</a> and after executing these commands I was surprised and found that on my system different python versions were running than I expected.</p>



<p>I found that there must be a problem when you install different Python versions on a Mac and I was looking for an easy way to switch between these versions. Switching between the versions is necessary because when you are a developer you might have the need to run your code on a certain version. So it has to be easy to install different python versions on your Mac and to switch between them as needed. There are of course several ways of dealing with this matter. I decided to use the version manager <a href="https://github.com/pyenv/pyenv">Pyenv</a>. But more on that later. First of all, back to my initial situation.</p>



<h2 class="wp-block-heading">Initial Situation</h2>



<p>It all started with a <a href="https://brew.sh/">Homebrew</a> error message after my update to Mac OS Big Sur (Mac OS 11). I had python 2 and 3 installed on my system with <a href="https://brew.sh/">Homebrew</a>. I had carried out these installations under Catalina. The <code>brew doctor</code> command gave me the error message saying I had installed kegs without a formula and I should uninstall python@2 because it is an outdated and no longer supported python version. What ?</p>



<p>My first check was on the <code>/usr/local/bin</code> directory because I wanted to know whether the python binaries had been linked correctly from <a href="https://brew.sh/">Homebrew</a>.</p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % ls -l /usr/local/bin/python*
lrwxr-xr-x  1 patrick  admin   32  6 Mär 10:23 python -&gt; ../Cellar/python@2/2.7.17/bin/python
lrwxr-xr-x  1 patrick  admin   32  6 Mär 10:23 python2 -&gt; ../Cellar/python@2/2.7.17/bin/python2
lrwxr-xr-x  1 patrick  admin   32  6 Mär 10:23 python2.7 -&gt; ../Cellar/python@2/2.7.17/bin/python2.7
</code></pre>



<p>Here it seems to me that only python 2 has been installed by Homebrew and the binary links all refer to the python@2 directory in the Homebrew Cellar.  My second check was on the Hombrew Cellar directory because I wanted to know whether there are Formulars of the two python versions available.</p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % ls -l /usr/local/Cellar/python*
drwxr-xr-x  3 patrick  staff  96 26 Feb 18:46 python@2
drwxr-xr-x  3 patrick  staff  96 26 Feb 18:46 python@3.8
</code></pre>



<p>This made it clear: Python 2 is correctly installed and linked in the Cellar (but out of date) but Python 3 was obviously not installed correctly (no binary links in <code>/usr/local/bin</code>). I understood that this must be the message from Homebrews error message. But then I was curious what the version check would tell me.</p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % which python
/usr/local/bin/python
patrick@PatrickMBNeu ~ % python --version
2.7.17
patrick@PatrickMBNeu ~ % which python3
/usr/bin/python3
patrick@PatrickMBNeu ~ % python3 --version
3.8.2
</code></pre>



<p>The command <code>which python</code> refers to the python 2 version installed with Homebrew in <code>/usr/local/bin</code> but what the hell is in <code>/usr/bin</code> ? </p>



<p>I googled around a bit and <a href="https://medium.com/faun/the-right-way-to-set-up-python-on-your-mac-e923ffe8cf8e">finally I found out</a> that it must be the python version that comes with Mac OS. So the command <code>which python3</code> refers to the python 3 version pre-installed on the Mac in <code>/usr/bin</code>.  And I learned that it must be avoided in any case to remove these so-called System Python Versions from the system. Apple install in <code>/usr/bin</code> while Homebrew install in <code>/usr/local/bin</code> and <code>/usr/local/Cellar</code>. So stay away from everything that is installed in <code>/usr/bin</code> with regard to Python.</p>



<p>Then I wanted to understand what Apple installed in <code>/usr/bin</code>.</p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % ls -l /usr/bin/python*
lrwxr-xr-x  1 root  wheel      75  1 Jan  2020 /usr/bin/python -&gt; ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
lrwxr-xr-x  1 root  wheel      75  1 Jan  2020 /usr/bin/python2 -&gt; ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
lrwxr-xr-x  1 root  wheel      75  1 Jan  2020 /usr/bin/python2.7 -&gt; ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
-rwxr-xr-x  1 root  wheel  137552  1 Jan  2020 /usr/bin/python3
patrick@PatrickMBNeu ~ % 
</code></pre>



<p>Apple apparently installs Python 2 and Python 3. But the command  <code>which python</code> clearly tells me (see above) that the Python 2 version of Homebrew from <code>/usr/local/bin</code> is currently active in some way, while the command <code>which python3</code> apparently refers to the System Python 3 version in <code>/usr/bin</code>.</p>



<p>How do I get the mess cleaned up ?</p>



<p>I decided to uninstall the python 2 version of Homebrew normally with the command <code>brew uninstall python@2</code>. And I also removed manually the <code>/usr/local/Cellar/python@3.8</code> directory. Then I checked the python versions again.<br></p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % which python
/usr/bin/python
patrick@PatrickMBNeu ~ % python --version
2.7.16
patrick@PatrickMBNeu ~ % which python3
/usr/bin/python3
patrick@PatrickMBNeu ~ % python3 --version
3.8.2
</code></pre>



<p>I was satisfied with the result. Both System Pythons in <code>/usr/bin</code> are currently active on my system and this is exactly what I wanted to achieve with my clean up. I can now think about how I would like to manage other, different python versions on my system. And this is exactly where I come back to <a href="https://github.com/pyenv/pyenv">Pyenv</a>.</p>



<h2 class="wp-block-heading">Managing Python on Mac OS with Pyenv</h2>



<p>First I install <a href="https://github.com/pyenv/pyenv">Pyenv</a> with Homebrew. </p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % brew update
patrick@PatrickMBNeu ~ % brew install pyenv
</code></pre>



<p>Then I create a <code>~/.zshrc</code> file in my home directory and add the command <code>pyenv init</code> at the end of the <code>~/.zshrc</code> configuration file to enable pyenv shims in my <code>PATH</code> variable.</p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % echo -e 'eval "$(pyenv init -)" ' &gt;&gt; ~/.zshrc
patrick@PatrickMBNeu ~ % cat .zshrc

eval "$(pyenv init -)"

patrick@PatrickMBNeu ~ % 
</code></pre>



<p>It is very important to make sure that the command  <code>eval "$(pyenv init -)"</code> is placed at the end of the shell configuration because it manipulates the <code>PATH</code> environment variable during the shell initialization.</p>



<p>Then I close the terminal and restart it again. </p>



<p>With the command <code>pyenv versions</code> you can check the existing python versions on your Mac. After my cleanup the only version on my Mac is the System Python and marked with <code>system</code>. </p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % pyenv versions     
* system (set by /Users/patrick/.pyenv/version)
patrick@PatrickMBNeu ~ % python --version
Python 2.7.16
patrick@PatrickMBNeu ~ % python3 --version
Python 3.8.2
patrick@PatrickMBNeu ~ %
</code></pre>



<p>When you check the version of the current System Python with the command <code>python</code> <code>--``version</code> and <code>python3</code> <code>--``version</code> you see that I still run the System Python Versions 2.7.16 and 3.8.2. Thats what I expected. </p>



<p>With Pyenv you can also install Python using the <code>pyenv install</code> command. With the command <code>pyenv install --list</code> you can list all available Python version that can be installed. This would be a long list but you can pipe it into grep to restrict the displayed list a little. Here I restrict the list to all available Python 3.8.* and 3.9.* versions. </p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % pyenv install --list | grep " 3\.&#91;89]"  
  3.8.0
  3.8-dev
  3.8.1
  3.8.2
  3.8.3
  3.8.4
  3.8.5
  3.8.6
  3.8.7
  3.9.0
  3.9-dev
  3.9.1
patrick@PatrickMBNeu ~ % 
</code></pre>



<p>Then I install Python 3.9.1 which is the latest Python available at the time of writing this article.</p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % pyenv install 3.9.1
</code></pre>



<p>Then I check the existing pythons again with <code>pyenv versions</code> and I can already see that the 3.9.1 version has been added. Now comes the real advantage of pyenv. With the command <code>pyenv global</code> I set the 3.9.1 version as the currently active one.</p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % pyenv versions     
* system (set by /Users/patrick/.pyenv/version)
  3.9.1
patrick@PatrickMBNeu ~ % pyenv global 3.9.1 
patrick@PatrickMBNeu ~ % pyenv versions   
  system
* 3.9.1 (set by /Users/patrick/.pyenv/version)
patrick@PatrickMBNeu ~ % python --version 
Python 3.9.1
patrick@PatrickMBNeu ~ % python3 --version 
Python 3.9.1
patrick@PatrickMBNeu ~ % python
Python 3.9.1 (default, Mar  8 2021, 18:50:54) 
&#91;Clang 12.0.0 (clang-1200.0.32.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; exit()
patrick@PatrickMBNeu ~ %  
</code></pre>



<p>I check again if the default python is now set to 3.9.1 using the command <code>python</code> <code>--``version</code>. The output in the terminal shows the active version marked with a star. This is Python 3.9.1 and exactly what I expected.  Then I login into the interactive python command interpreter and this also confirmed that it is currently the 3.9.1 version. </p>



<p>So I manage my Pythons on my Mac OS Big Sur from now on with Pyenv. </p>



<h2 class="wp-block-heading">Make Pyenv working perfectly with Homebrew</h2>



<p>When I finished installing Pyenv everything worked fine until I tried to use the brew doctor command to check my Homebrew installations. </p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % brew doctor
Warning: "config" scripts exist outside your system or Homebrew directories.
`./configure` scripts often look for *-config scripts to determine if
software packages are installed, and what additional flags to use when
compiling and linking.

Having additional scripts in your path can confuse software installed via
Homebrew if the config script overrides a system or Homebrew provided
script of the same name. We found the following "config" scripts:

    /Users/patrick/.pyenv/shims/python-config
    /Users/patrick/.pyenv/shims/python3-config
    /Users/patrick/.pyenv/shims/python3.9-config

patrick@PatrickMBNeu ~ %
</code></pre>



<p>I googled a little and I <a href="https://titanwolf.org/Network/Articles/Article?AID=f6d65982-5922-4ccc-9244-8d3dfa687e4c#gsc.tab=0">found out this</a>. Very interesting Article about the <code>PATH</code> settings I enforced in my <code>~/.zshrc</code> file when I installed Pyenv (see above). </p>



<p>Then I checked my environment variables with the command <code>env</code>.</p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % env
TMPDIR=/var/folders/zy/3s2n4mh502z3320837q80qdm0000gp/T/
__CFBundleIdentifier=com.apple.Terminal
XPC_FLAGS=0x0
TERM=xterm-256color
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.ZIRHZWPkYD/Listeners
XPC_SERVICE_NAME=0
TERM_PROGRAM=Apple_Terminal
TERM_PROGRAM_VERSION=440
TERM_SESSION_ID=53DE5B52-55E2-4D61-A4E4-7F47D5C401AC
SHELL=/bin/zsh
HOME=/Users/patrick
LOGNAME=patrick
USER=patrick
PATH=/Users/patrick/.pyenv/shims:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/MacGPG2/bin
SHLVL=1
PWD=/Users/patrick
OLDPWD=/Users/patrick
PYENV_SHELL=zsh
LANG=de_DE.UTF-8
_=/usr/bin/env
patrick@PatrickMBNeu ~ % 
</code></pre>



<p>The problem seems to be the <code>PATH</code> which is set by the entry <code>eval "$ (pyenv init -)"</code> in my <code>~/.zshrc</code> file.<br></p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % cat .zshrc
eval "$(pyenv init -)"

patrick@PatrickMBNeu ~ %
</code></pre>



<p>This entry leads to that <code>/Users/patrick/.pyenv/shims</code> is set at the beginning of the <code>PATH</code> variable when <code>zsh</code> is executed. </p>



<p>When you look at the complete <code>PATH</code> you see that the command <code>brew doctor</code> can be executed without specifying  <code>/usr/local/bin/brew</code> because the required path specification <code>/usr/local/bin</code> is also available but further back. So brew reads first the path <code>/Users/patrick/.pyenv/shims</code> and only then the path <code>/usr/local/bin</code> and exactly there in <code>/Users/patrick/.pyenv/shims</code> are the <code>*-config</code> files used from Pyenv. So it seems to be that brew has problems with these config files.</p>



<p>Since these config files seems to confuse brew in some way, the best would be if brew could somehow ignore these files. This is possible if we define an <code>alias</code> environment variable. We can define <code>brew</code> as an alias and then instruct <code>zsh</code> that in the event that <code>brew</code> is called a specific <code>PATH</code> applies namely the <code>PATH</code> without the shims directory. For this we have to adapt the <code>~/.zshrc</code> as follows.</p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % cat .zshrc
alias brew='PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin brew'
eval "$(pyenv init -)"
patrick@PatrickMBNeu ~ %
</code></pre>



<p>After restarting the terminal I was able to run the <code>brew doctor</code> command without this error message. The problem is solved.</p>



<pre class="wp-block-code"><code>patrick@PatrickMBNeu ~ % brew update 
Already up-to-date.
patrick@PatrickMBNeu ~ % brew doctor     
Your system is ready to brew.
patrick@PatrickMBNeu ~ % 
</code></pre>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
