What is it like moving from PHP to Python? Part 2 explores Python’s float, string, and list operators and operations.
- Deep Dive Part 1 - overview, conventions, everything is an object
- Deep Dive Part 2 - primitives, lists, operators, and operations
- Deep Dive Part 3 - conditions, type checking, and loops
Using the broad overview from learningpython.org, we’ll examine the ins and outs of Python from a PHP developer’s perspective, while showing the equivalent PHP and Python code side-by-side.
Clone github.com/bill-c-martin/python-for-php-devs to get a Python environment setup and to follow along with the code examples in this series.
In Part 2 of this series, we will examine these in more detail to see how they compare in Python vs PHP:
- Numbers, floats, and arithmetic
- Strings and their various operations
- Lists, iteration, and operations
- Multiple variable assignment
Table of Contents
Numbers
Like PHP, Python is dynamically-typed. Therefore, numbers and arithmetic in Python more or less behave how they do in PHP, with a few key differences.
Floats
Displaying floats in Python works better, since it doesn’t require a special function to regain lost .0
’s like PHP.
PHP
$x = 2;
echo $x;
// php is terrible for this
$y = 3.0;
var_dump( number_format((float)$x, 1, '.', '') );
// even when typecasting to float, you still need number_format()
$x = (float) 4;
var_dump( number_format($x, 1, '.', '') );
Python
Simplicity.
x = 2
print(x)
y=3.0
print(x) # prints 3.0
z=float(4)
print(z) # prints 4.0
Arithmetic
Arithmetic in Python is mostly what you’d expect, coming from PHP.
+
, -
, *
, /
, and %
all do exactly what you’d think they’d do for numeric arithmetic.
And for non-numeric types, as covered in Part 1 (magic methods), they behave differently.
However, there are a couple Python arithmetic operators not found in PHP:
**
: exponential multiplication//
: floor division
PHP does of course have this functionality through its pow()
and floor()
methods. And to be fair, those **
and //
“operators” in Python are just syntax sugar for magic methods anyways.
But they are still worth calling out, because to PHP eyes, **
looks like a syntax error, and //
looks like a comment!
PHP
# 5^3 power
echo pow(5,3); // prints: 125
# Floor division:
echo floor(9 / 2); // prints: 4
echo floor(9.0 / 2.0); // prints: 4
echo floor(-11 / 3); // prints: -4
echo floor(-11.0 / 3); // prints: -4
Python
# 5^3 power
print(5 ** 3) # prints: 125
# Floor division:
print(9 // 2) # prints: 4
print(9.0 // 2.0) # prints: 4.0
print(-11 // 3) # prints: -4
print(-11.0 // 3) # prints: -4.0
One other interesting thing about floor division worth calling out for Python is that last example, above. Notice that floor division involving one or more floats will result in a float being returned, even though floor division, by definition, results in a whole number.
On the topic of automatic type conversion, it’s also worth noting that like PHP’s Type Juggling feature, Python also performs automatic type conversion depending on the context.
For example, dividing an int
by a float
produces a float
in both:
PHP
$x = 1 + 2 * 3 / 4.0;
var_dump($x); // prints: 2.5
Python
x = 1 + 2 * 3 / 4.0
print(x) # prints: 2.5
Strings
Concatenation
String concatenation in Python resembles JavaScript, which is similar enough to PHP.
PHP
echo 'hello' . ' ' . 'world';
Python
print('hello' + ' ' + 'world')
Remember from Part 1: +
is just the __add__
magic method that all strings have, which in the case of strings, performs concatenation.
Repetition
String repetition in Python is an interesting Ruby-esque quirk.
To repeat a string, you multiply it by an integer. For example: 'Ho ' * 3
.
PHP
str_repeat('Repeat', 3); // prints: RepeatRepeatRepeat
Python
print('Repeat' * 3) # prints: RepeatRepeatRepeat
Same as +
, this *
operator is just the __mul__
method that all strings have, which returns a repeated string n times. As in: 'Repeat.__mul__(3)
.
Substitution
String substition will feel familiar, with some key differences.
With PHP:
echo
andprint()
both output dataprintf()
andsprintf()
both substitute variables in strings
With Python, everything can just go through print()
.
Except when it doesn’t. There’s actually 3 different ways.
Let’s start with the %
way:
Python
# single substitution
name = 'john'
print('Hello, %s' % name)
# 2 or more substitutions
first = 'john'
last = 'smith'
print('Hello, %s %s' % (first, last))
It must surely seem strange to see that %
operator preceding the tuple of variables like that, which is inherently confusing since %
is supposed to do.. modulo things.
But like +
and *
, %
is just syntactic sugar for __mod__
. So what is really happening here is 'Hello, %s %s'.__mod__( (first, last) )
.
Why is the string interpolation operator the modulo operator? Nobody knows.
And what about that (first, last)
part, and its “redundant” parenthesis? Remember, that is a tuple: a collection of constants basically. It’s kind of like passing an array into a function in PHP. If you lose the parenthesis, you would be passing two strings, instead of a single tuple collection of strings.
You can also do some elegantly useful formatting things inside strings with %s
, %d
, and %f
:
Python
one = 1
two = 2.0
three = 'three'
# prints: Counting: 1, 2.000000, three
print("Counting: %d, %f, %s" % (one, two, three))
# Rounding. Prints: More: 1.15656566, Less: 1.1566, Even less: 1.2
y = 1.15656565656
print("More: %.8f, Less: %.4f, Even less: %.1f" % (y,y,y))
# Lower/uppercase. Prints: Int: 14, lowercase x: e, uppercase x: E
x = 14
print('Int: %d, lowercase x: %x, uppercase x: %X' % (x,x,x))
There’s also str.format()
, which is overly verbose, and rather unintuitive how one can’t just pass the variables into the function as format(first, last, age)
:
Python
first = "John"
last = "Smith"
age = 22
print("Hello, {first} {last}, who is {age} years old.".format(first=first, last=last, age=age) )
And finally, there are f-strings: the newest way to accomplish string interpolation.
Python
first = "John"
last = "Smith"
age = 22
print(f'Hello, {first} {last}, who is {age} years old.')
Note that f
hugging the front of the string.
Also, there’s supposed to be a joke that goes:
Do you love strings in Python?
f’Yes!’
Operations
In Python, since strings are objects, they contain a whole pile of methods useful for doing operations, not to mention all those __special_methods__
discussed previously.
As a PHP developer, chaining these string methods off of strings would feel familiar if you’ve written TypeScript before.
Python strings have two types of string operation syntax:
'foo'.method_name()
: for string positions, splitting, upper/lower, etc'foo'[x:x:x]
: for slicing, using a List-like syntax
This is a departure from PHP, where string processing is always done through standalone functions available in the language itself, like strpos()
, explode()
, strtoupper()
, and substr()
.
Let’s start with Python string operations that use that method syntax, and compare them to PHP.
Python
x = 'Hello world'
# length
print(len(x)) # prints: 11
# character position
print(x.index('o')) # prints: 4
# counting occurrences
print(x.count('l')) # prints: 3
# transforming
print(x.upper()) # prints: hello world
print(x.lower()) # prints: HELLO WORLD
# splitting
print(x.split(" ")) # Prints: ['Hello', 'world']
print(len(x.split(" "))) # Prints: 2
PHP
$x = 'Hello world';
// length
echo strlen($x); // prints: 11
// character position
echo strpos($x, 'o'); // prints: 4
// counting occurrences
echo substr_count($x, 'l'); // prints: 3
// transforming
echo strtoupper($x); // prints: hello world
echo strtolower($x); // prints: HELLO WORLD
// splitting
print_r(explode(' ', $x)); // Prints: ['Hello', 'world']
echo count(explode(' ', $x)); // Prints: 2
Pretty similar, with Python being more elegant and consistent in naming, which is nothing suprising, because PHP.
Now, let’s look the Python string operations tha use that array/List syntax, and compare them to PHP.
Python
x = 'Hello world'
# string slicing
print(x[3:7]) # prints: lo w
# single character capturing
print(x[3]) # prints: l
# slicing to end-of-string
print(x[3:]) # prints: lo world
# slicing from beginning-of-string
print(x[:7]) # prints: Hello w
# slicing last n characters
print(x[-3:]) # prints: rld
PHP
$x = 'Hello world';
// string slicing
echo substr($x, 3, 4); // prints: lo w
// single character capturing
echo substr($x, 3, 1); // prints: l
// slicing to end-of-string
echo substr($x, 3); // prints: lo world
// slicing from beginning-of-string
echo substr($x, 0, 7); // prints: Hello w
// slicing last n characters
echo substr($x, -3, 3); // prints: rld
Again, pretty similar. Just syntac sugar really.
Now let’s look at some string operations where Python and PHP can be wildly different.
Up first is starts/ends with, which PHP did not have a native equivalent until PHP 8:
Python
x = 'Hello world'
print(x.startswith('Hello')) # prints: True
print(x.endswith('rld')) # prints: True
PHP
$x = 'Hello world';
// Before PHP 8..
echo substr($x, 0, strlen('Hello')) === 'Hello'); // prints: true
echo substr($x, -strlen('rld')) === 'rld'); // prints: true
// After PHP 8..
echo str_starts_with($x, 'Hello'); // prints: true
echo str_ends_with($x, 'rld'); // prints: true
It suprisingly has taken PHP until 2020 to have something non-tedious for that!
Up second is string stepping, which is certainly a Python string operation I have never seen in PHP before:
Python
x = 'Hello world'
# slicing while stepping n characters
print(x[1:7:2]) # prints: el
# string reversing, using stepping
print(x[::-1]) # prints; dlrow olleH
Of course, PHP has strrev()
for string reversing though.
So what is string stepping in Python? It’s that 3rd “parameter” and is a like an interval or iterator.
[1:7]
is slicing out the 2nd to 8th characters from the string, but [1:7:2]
is doing the same, except skip every other character while doing that.
[:]
is basically request every character from the beginning until the end of the string, but [::-1]
is doing the same, except go backwards for each character returned.
So the equivalents in PHP would be a mess of strlen()
, explode
for array conversion, for
loops for iterating, and iterators like $i+2
to mimic the stepping.
The take away here is that although PHP and Python have a lot of similarity in string operations, it’s really Python’s terse syntax and slicing flexibility that are a win, and lends itself well to the machine learning community slicing and dicing up data to train algorithms.
Lists
PHP numeric arrays are called Lists in Python, and the two are quite similar, with some key differences.
Appending and Looping
However, pushing elements and looping feels more like Javascript:
PHP
// Farewell to our beloved push syntax
$mylist = [];
$mylist[] = 1;
$mylist[] = 'two';
$mylist[] = 3.0;
// Array looping
foreach($mylist as $x) {
echo $x;
}
Python
# append() adds new elements
mylist = []
mylist.append(1)
mylist.append('two')
mylist.append(3.0)
# Array looping
for x in mylist:
print(x)
Initialization
Like PHP, you can declare and initialize a List all in one go. The syntax is the same:
PHP
$that_list = [1,2,3,4];
foreach($that_list as $x) {
echo $x;
}
Python
that_list = [1,2,3,4]
for x in that_list:
print(x)
Out of Bounds Elements
Accessing non-existent elements earns you an exception in Python, instead of PHP’s warnings:
PHP
$mylist = [1,2,3,4];
echo $mylist[6]; // causes a warning, but the show goes on.
Python
mylist = [1,2,3,4]
try:
print(mylist[6])
except:
print('good thing I caught this exception')
Repetition
That repeating *
“operator” from earlier is back already. It works for Lists too.
Which means List objects have their own defined __mul__
method like strings do.
PHP
Note how there is no elegant way to do this in PHP with arrays, not even an ArrayObject:
$source_list = [1,2,3];
$new_list = [];
for($i=1; $i<=10; $i++) {
$new_list = array_merge($source_list, $new_list);
}
print_r($new_list);
Python
But in Python: Simplicity.
print([1,2,3] * 10)
Concatenation
Moving along with the List arithmetic theme, that intuitive *
way of working with Lists in Python applies with the +
operator as well:
PHP
$even = [2,4,6,8];
$odd = [1,3,5,7];
print_r( array_merge($even, $odd) ); // prints [2,4,6,8,1,3,5,7]
Python
Simplicity.
even = [2,4,6,8]
odd = [1,3,5,7]
print(even + odd) # prints [2,4,6,8,1,3,5,7]
+
is syntactic sugar for List.__add__
in this case.
Multiple Variable Assignments
Assignments are mostly what you’d expect, but there are some interesting differences between PHP vs Python to call out here with multiple variable assignments.
Multiple Variable Assignments to Same Value
Initializing a bunch of variables to a single value is what you would expect:
PHP
$a = $b = $c = 1;
var_dump($a, $b, $c); // prints: 1 1 1
Python
a = b = c = 1
print(a, b, c) # prints: 1 1 1
However, there is a curveball when doing this with Lists in Python.
Consider the below 3 variables assigned to the array. As we know, PHP copies the array into each assignment. So you are free to modify one variables without impacting the others.
Not so with Python. Python “points” all 3 variables to the same array in memory. Meaning, when the array changes, all 3 variables change with it.
PHP
$a = $b = $c = [1];
$b[] = 2;
var_dump($a, $b, $c); // prints: [1] [1,2] [1]
Python
a = b = c = [1]
b.append(2)
print(a, b, c) # prints: [1,2] [1,2] [1,2]
Multiple Variable Assignments to Multiple Values
This one is worth noting since I’ve rarely seen this in PHP, but frequently in Python.
PHP
Historically, we usually used list()
to capture multiple return variables from a function into multiple variables:
function some_function(){ return [1, 2, 3]; };
list($a, $b, $c) = some_function();
There’s also square bracket syntactic sugar available since PHP7. Both can be used to also just assign multiple variables on a one-liner:
list($x, $y, $z) = [1, 2, 3];
var_dump($x, $y, $z); // prints: 1 2 3
[$x, $y, $z] = [1, 2, 3];
var_dump($x, $y, $z); // prints: 1 2 3
Python
However, Python loses all the syntactic fluff and just has comma-separation and that’s it:
a, b, c = 1, 2, 3
print(a, b, c) # prints: 1 2 3
Conclusion
- Python handles float formatting better than PHP
- Python arithmetic is highly similar, but has those
**
and//
power and floor division operators - Python makes consistent use of operators performing operations, instead of PHP’s myriad global methods
- Python lists behave a bit differently than PHP arrays
In Part 3, we will get into Python loops, conditions, functions, and classes, while comparing it to PHP-equivalent code every step of the way.
- Deep Dive Part 1 - overview, conventions, everything is an object
- Deep Dive Part 2 - primitives, lists, operators, and operations
- Deep Dive Part 3 - conditions, type checking, and loops