Examples :
Input: list1 = [10, 10, 0, 0, 10] list2 = [10, 10, 10, 0, 0] Output: Yes Explanation: yes they are circularly identical as when we write the list1 last index to second last index, then we find it is circularly same with list1 Input: list1 = [10, 10, 10, 0, 0] list2 = [1, 10, 10, 0, 0] Output: No
Method 1. Using list traversal
Using traversing , we have to double the given list. Check for any x (0 & lt; = n) for any x + n and compare with list2 to see if list1 and list2 are the same, if both are the same then list2 is cyclically identical. Check this property using two loops. The first loop will run from 0 to len (list1) and then check if the index (x to x + n) is the same as list2, if yes then returns true, otherwise returns false.
Python implementation of the above approach:

Exit :
Yes No
C tutorial 1: using the map () function
Using the Python builtin function map (), we can do this in one step where we need to map list2 to a string and then see if it exists when mapping a double from list1 (2 * list1) to on another line.
Below is the Python implementation of the above approach:

Exit:
Yes No
In Python, with Matplotlib, how can a scatter plot with empty circles be plotted? The goal is to draw empty circles around some of the colored disks already plotted by scatter()
, so as to highlight them, ideally without having to redraw the colored circles.
I tried facecolors=None
, to no avail.
surprisingly I didn"t find a straightforward description on how to draw a circle with matplotlib.pyplot (please no pylab) taking as input center (x,y) and radius r. I tried some variants of this:
import matplotlib.pyplot as plt
circle=plt.Circle((0,0),2)
# here must be something like circle.plot() or not?
plt.show()
... but still didn"t get it working.
You said you couldn‚Äôt get the golden spiral method to work and that‚Äôs a shame because it‚Äôs really, really good. I would like to give you a complete understanding of it so that maybe you can understand how to keep this away from being ‚Äúbunched up.‚Äù
So here‚Äôs a fast, nonrandom way to create a lattice that is approximately correct; as discussed above, no lattice will be perfect, but this may be good enough. It is compared to other methods e.g. at BendWavy.org but it just has a nice and pretty look as well as a guarantee about even spacing in the limit.
To understand this algorithm, I first invite you to look at the 2D sunflower spiral algorithm. This is based on the fact that the most irrational number is the golden ratio (1 + sqrt(5))/2
and if one emits points by the approach ‚Äústand at the center, turn a golden ratio of whole turns, then emit another point in that direction,‚Äù one naturally constructs a spiral which, as you get to higher and higher numbers of points, nevertheless refuses to have welldefined ‚Äòbars‚Äô that the points line up on.^{(Note 1.)}
The algorithm for even spacing on a disk is,
from numpy import pi, cos, sin, sqrt, arange
import matplotlib.pyplot as pp
num_pts = 100
indices = arange(0, num_pts, dtype=float) + 0.5
r = sqrt(indices/num_pts)
theta = pi * (1 + 5**0.5) * indices
pp.scatter(r*cos(theta), r*sin(theta))
pp.show()
and it produces results that look like (n=100 and n=1000):
The key strange thing is the formula r = sqrt(indices / num_pts)
; how did I come to that one? ^{(Note 2.)}
Well, I am using the square root here because I want these to have evenarea spacing around the disk. That is the same as saying that in the limit of large N I want a little region R ‚àà (r, r + dr), Œò ‚àà (Œ∏, Œ∏ + dŒ∏) to contain a number of points proportional to its area, which is r dr dŒ∏. Now if we pretend that we are talking about a random variable here, this has a straightforward interpretation as saying that the joint probability density for (R, Œò) is just c r for some constant c. Normalization on the unit disk would then force c = 1/œÄ.
Now let me introduce a trick. It comes from probability theory where it‚Äôs known as sampling the inverse CDF: suppose you wanted to generate a random variable with a probability density f(z) and you have a random variable U ~ Uniform(0, 1), just like comes out of random()
in most programming languages. How do you do this?
Now the goldenratio spiral trick spaces the points out in a nicely even pattern for Œ∏ so let‚Äôs integrate that out; for the unit disk we are left with F(r) = r^{2}. So the inverse function is F^{1}(u) = u^{1/2}, and therefore we would generate random points on the disk in polar coordinates with r = sqrt(random()); theta = 2 * pi * random()
.
Now instead of randomly sampling this inverse function we‚Äôre uniformly sampling it, and the nice thing about uniform sampling is that our results about how points are spread out in the limit of large N will behave as if we had randomly sampled it. This combination is the trick. Instead of random()
we use (arange(0, num_pts, dtype=float) + 0.5)/num_pts
, so that, say, if we want to sample 10 points they are r = 0.05, 0.15, 0.25, ... 0.95
. We uniformly sample r to get equalarea spacing, and we use the sunflower increment to avoid awful ‚Äúbars‚Äù of points in the output.
The changes that we need to make to dot the sphere with points merely involve switching out the polar coordinates for spherical coordinates. The radial coordinate of course doesn"t enter into this because we"re on a unit sphere. To keep things a little more consistent here, even though I was trained as a physicist I"ll use mathematicians" coordinates where 0 ‚â§ œÜ ‚â§ œÄ is latitude coming down from the pole and 0 ‚â§ Œ∏ ‚â§ 2œÄ is longitude. So the difference from above is that we are basically replacing the variable r with œÜ.
Our area element, which was r dr dŒ∏, now becomes the notmuchmorecomplicated sin(œÜ) dœÜ dŒ∏. So our joint density for uniform spacing is sin(œÜ)/4œÄ. Integrating out Œ∏, we find f(œÜ) = sin(œÜ)/2, thus F(œÜ) = (1 ‚àí cos(œÜ))/2. Inverting this we can see that a uniform random variable would look like acos(1  2 u), but we sample uniformly instead of randomly, so we instead use œÜ_{k} = acos(1 ‚àí 2 (k + 0.5)/N). And the rest of the algorithm is just projecting this onto the x, y, and z coordinates:
from numpy import pi, cos, sin, arccos, arange
import mpl_toolkits.mplot3d
import matplotlib.pyplot as pp
num_pts = 1000
indices = arange(0, num_pts, dtype=float) + 0.5
phi = arccos(1  2*indices/num_pts)
theta = pi * (1 + 5**0.5) * indices
x, y, z = cos(theta) * sin(phi), sin(theta) * sin(phi), cos(phi);
pp.figure().add_subplot(111, projection="3d").scatter(x, y, z);
pp.show()
Again for n=100 and n=1000 the results look like:
I wanted to give a shout out to Martin Roberts‚Äôs blog. Note that above I created an offset of my indices by adding 0.5 to each index. This was just visually appealing to me, but it turns out that the choice of offset matters a lot and is not constant over the interval and can mean getting as much as 8% better accuracy in packing if chosen correctly. There should also be a way to get his R_{2} sequence to cover a sphere and it would be interesting to see if this also produced a nice even covering, perhaps asis but perhaps needing to be, say, taken from only a half of the unit square cut diagonally or so and stretched around to get a circle.
Those ‚Äúbars‚Äù are formed by rational approximations to a number, and the best rational approximations to a number come from its continued fraction expression, z + 1/(n_1 + 1/(n_2 + 1/(n_3 + ...)))
where z
is an integer and n_1, n_2, n_3, ...
is either a finite or infinite sequence of positive integers:
def continued_fraction(r):
while r != 0:
n = floor(r)
yield n
r = 1/(r  n)
Since the fraction part 1/(...)
is always between zero and one, a large integer in the continued fraction allows for a particularly good rational approximation: ‚Äúone divided by something between 100 and 101‚Äù is better than ‚Äúone divided by something between 1 and 2.‚Äù The most irrational number is therefore the one which is 1 + 1/(1 + 1/(1 + ...))
and has no particularly good rational approximations; one can solve œÜ = 1 + 1/œÜ by multiplying through by œÜ to get the formula for the golden ratio.
For folks who are not so familiar with NumPy  all of the functions are ‚Äúvectorized,‚Äù so that sqrt(array)
is the same as what other languages might write map(sqrt, array)
. So this is a componentbycomponent sqrt
application. The same also holds for division by a scalar or addition with scalars  those apply to all components in parallel.
The proof is simple once you know that this is the result. If you ask what"s the probability that z < Z < z + dz, this is the same as asking what"s the probability that z < F^{1}(U) < z + dz, apply F to all three expressions noting that it is a monotonically increasing function, hence F(z) < U < F(z + dz), expand the right hand side out to find F(z) + f(z) dz, and since U is uniform this probability is just f(z) dz as promised.
Python has no builtin encryption schemes, no. You also should take encrypted data storage serious; trivial encryption schemes that one developer understands to be insecure and a toy scheme may well be mistaken for a secure scheme by a less experienced developer. If you encrypt, encrypt properly.
You don‚Äôt need to do much work to implement a proper encryption scheme however. First of all, don‚Äôt reinvent the cryptography wheel, use a trusted cryptography library to handle this for you. For Python 3, that trusted library is cryptography
.
I also recommend that encryption and decryption applies to bytes; encode text messages to bytes first; stringvalue.encode()
encodes to UTF8, easily reverted again using bytesvalue.decode()
.
Last but not least, when encrypting and decrypting, we talk about keys, not passwords. A key should not be human memorable, it is something you store in a secret location but machine readable, whereas a password often can be humanreadable and memorised. You can derive a key from a password, with a little care.
But for a web application or process running in a cluster without human attention to keep running it, you want to use a key. Passwords are for when only an enduser needs access to the specific information. Even then, you usually secure the application with a password, then exchange encrypted information using a key, perhaps one attached to the user account.
The cryptography
library includes the Fernet recipe, a bestpractices recipe for using cryptography. Fernet is an open standard,
with ready implementations in a wide range of programming languages and it packages AES CBC encryption for you with version information, a timestamp and an HMAC signature to prevent message tampering.
Fernet makes it very easy to encrypt and decrypt messages and keep you secure. It is the ideal method for encrypting data with a secret.
I recommend you use Fernet.generate_key()
to generate a secure key. You can use a password too (next section), but a full 32byte secret key (16 bytes to encrypt with, plus another 16 for the signature) is going to be more secure than most passwords you could think of.
The key that Fernet generates is a bytes
object with URL and file safe base64 characters, so printable:
from cryptography.fernet import Fernet
key = Fernet.generate_key() # store in a secure location
print("Key:", key.decode())
To encrypt or decrypt messages, create a Fernet()
instance with the given key, and call the Fernet.encrypt()
or Fernet.decrypt()
, both the plaintext message to encrypt and the encrypted token are bytes
objects.
encrypt()
and decrypt()
functions would look like:
from cryptography.fernet import Fernet
def encrypt(message: bytes, key: bytes) > bytes:
return Fernet(key).encrypt(message)
def decrypt(token: bytes, key: bytes) > bytes:
return Fernet(key).decrypt(token)
Demo:
>>> key = Fernet.generate_key()
>>> print(key.decode())
GZWKEhHGNopxRdOHS4H4IyKhLQ8lwnyU7vRLrM3sebY=
>>> message = "John Doe"
>>> encrypt(message.encode(), key)
"gAAAAABciT3pFbbSihD_HZBZ8kqfAj94UhknamBuirZWKivWOukgKQ03qE2mcuvpuwCSuZX_Xkud0uWQLZ5eaOwLC0Ccnepg=="
>>> token = _
>>> decrypt(token, key).decode()
"John Doe"
You can use a password instead of a secret key, provided you use a strong key derivation method. You do then have to include the salt and the HMAC iteration count in the message, so the encrypted value is not Fernetcompatible anymore without first separating salt, count and Fernet token:
import secrets
from base64 import urlsafe_b64encode as b64e, urlsafe_b64decode as b64d
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
backend = default_backend()
iterations = 100_000
def _derive_key(password: bytes, salt: bytes, iterations: int = iterations) > bytes:
"""Derive a secret key from a given password and salt"""
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(), length=32, salt=salt,
iterations=iterations, backend=backend)
return b64e(kdf.derive(password))
def password_encrypt(message: bytes, password: str, iterations: int = iterations) > bytes:
salt = secrets.token_bytes(16)
key = _derive_key(password.encode(), salt, iterations)
return b64e(
b"%b%b%b" % (
salt,
iterations.to_bytes(4, "big"),
b64d(Fernet(key).encrypt(message)),
)
)
def password_decrypt(token: bytes, password: str) > bytes:
decoded = b64d(token)
salt, iter, token = decoded[:16], decoded[16:20], b64e(decoded[20:])
iterations = int.from_bytes(iter, "big")
key = _derive_key(password.encode(), salt, iterations)
return Fernet(key).decrypt(token)
Demo:
>>> message = "John Doe"
>>> password = "mypass"
>>> password_encrypt(message.encode(), password)
b"9Ljsw8IRM3XT1NDBbSBuQABhqCAAAAAAFyJdhiCPXms2vQHO7o81xZJn5r8_PAtro8Qpw48kdKrq4vt551BCUbcErb_GyYRz8SVsu8hxTXvvKOn9QdewRGDfwx"
>>> token = _
>>> password_decrypt(token, password).decode()
"John Doe"
Including the salt in the output makes it possible to use a random salt value, which in turn ensures the encrypted output is guaranteed to be fully random regardless of password reuse or message repetition. Including the iteration count ensures that you can adjust for CPU performance increases over time without losing the ability to decrypt older messages.
A password alone can be as safe as a Fernet 32byte random key, provided you generate a properly random password from a similar size pool. 32 bytes gives you 256 ^ 32 number of keys, so if you use an alphabet of 74 characters (26 upper, 26 lower, 10 digits and 12 possible symbols), then your password should be at least math.ceil(math.log(256 ** 32, 74))
== 42 characters long. However, a wellselected larger number of HMAC iterations can mitigate the lack of entropy somewhat as this makes it much more expensive for an attacker to brute force their way in.
Just know that choosing a shorter but still reasonably secure password won‚Äôt cripple this scheme, it just reduces the number of possible values a bruteforce attacker would have to search through; make sure to pick a strong enough password for your security requirements.
An alternative is not to encrypt. Don"t be tempted to just use a lowsecurity cipher, or a homespun implementation of, say Vignere. There is no security in these approaches, but may give an inexperienced developer that is given the task to maintain your code in future the illusion of security, which is worse than no security at all.
If all you need is obscurity, just base64 the data; for URLsafe requirements, the base64.urlsafe_b64encode()
function is fine. Don"t use a password here, just encode and you are done. At most, add some compression (like zlib
):
import zlib
from base64 import urlsafe_b64encode as b64e, urlsafe_b64decode as b64d
def obscure(data: bytes) > bytes:
return b64e(zlib.compress(data, 9))
def unobscure(obscured: bytes) > bytes:
return zlib.decompress(b64d(obscured))
This turns b"Hello world!"
into b"eNrzSM3JyVcozy_KSVEEAB0JBF4="
.
If all you need is a way to make sure that the data can be trusted to be unaltered after having been sent to an untrusted client and received back, then you want to sign the data, you can use the hmac
library for this with SHA1 (still considered secure for HMAC signing) or better:
import hmac
import hashlib
def sign(data: bytes, key: bytes, algorithm=hashlib.sha256) > bytes:
assert len(key) >= algorithm().digest_size, (
"Key must be at least as long as the digest size of the "
"hashing algorithm"
)
return hmac.new(key, data, algorithm).digest()
def verify(signature: bytes, data: bytes, key: bytes, algorithm=hashlib.sha256) > bytes:
expected = sign(data, key, algorithm)
return hmac.compare_digest(expected, signature)
Use this to sign data, then attach the signature with the data and send that to the client. When you receive the data back, split data and signature and verify. I"ve set the default algorithm to SHA256, so you"ll need a 32byte key:
key = secrets.token_bytes(32)
You may want to look at the itsdangerous
library, which packages this all up with serialisation and deserialisation in various formats.
Fernet builds on AECCBC with a HMAC signature to ensure integrity of the encrypted data; a malicious attacker can"t feed your system nonsense data to keep your service busy running in circles with bad input, because the ciphertext is signed.
The Galois / Counter mode block cipher produces ciphertext and a tag to serve the same purpose, so can be used to serve the same purposes. The downside is that unlike Fernet there is no easytouse onesizefitsall recipe to reuse on other platforms. AESGCM also doesn"t use padding, so this encryption ciphertext matches the length of the input message (whereas Fernet / AESCBC encrypts messages to blocks of fixed length, obscuring the message length somewhat).
AES256GCM takes the usual 32 byte secret as a key:
key = secrets.token_bytes(32)
then use
import binascii, time
from base64 import urlsafe_b64encode as b64e, urlsafe_b64decode as b64d
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.exceptions import InvalidTag
backend = default_backend()
def aes_gcm_encrypt(message: bytes, key: bytes) > bytes:
current_time = int(time.time()).to_bytes(8, "big")
algorithm = algorithms.AES(key)
iv = secrets.token_bytes(algorithm.block_size // 8)
cipher = Cipher(algorithm, modes.GCM(iv), backend=backend)
encryptor = cipher.encryptor()
encryptor.authenticate_additional_data(current_time)
ciphertext = encryptor.update(message) + encryptor.finalize()
return b64e(current_time + iv + ciphertext + encryptor.tag)
def aes_gcm_decrypt(token: bytes, key: bytes, ttl=None) > bytes:
algorithm = algorithms.AES(key)
try:
data = b64d(token)
except (TypeError, binascii.Error):
raise InvalidToken
timestamp, iv, tag = data[:8], data[8:algorithm.block_size // 8 + 8], data[16:]
if ttl is not None:
current_time = int(time.time())
time_encrypted, = int.from_bytes(data[:8], "big")
if time_encrypted + ttl < current_time or current_time + 60 < time_encrypted:
# too old or created well before our current time + 1 h to account for clock skew
raise InvalidToken
cipher = Cipher(algorithm, modes.GCM(iv, tag), backend=backend)
decryptor = cipher.decryptor()
decryptor.authenticate_additional_data(timestamp)
ciphertext = data[8 + len(iv):16]
return decryptor.update(ciphertext) + decryptor.finalize()
I"ve included a timestamp to support the same timetolive usecases that Fernet supports.
This is the approach that All –Ü—ï V–∞–∏—ñ—Çy follows, albeit incorrectly. This is the cryptography
version, but note that I include the IV in the ciphertext, it should not be stored as a global (reusing an IV weakens the security of the key, and storing it as a module global means it"ll be regenerated the next Python invocation, rendering all ciphertext undecryptable):
import secrets
from base64 import urlsafe_b64encode as b64e, urlsafe_b64decode as b64d
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
backend = default_backend()
def aes_cfb_encrypt(message, key):
algorithm = algorithms.AES(key)
iv = secrets.token_bytes(algorithm.block_size // 8)
cipher = Cipher(algorithm, modes.CFB(iv), backend=backend)
encryptor = cipher.encryptor()
ciphertext = encryptor.update(message) + encryptor.finalize()
return b64e(iv + ciphertext)
def aes_cfb_decrypt(ciphertext, key):
iv_ciphertext = b64d(ciphertext)
algorithm = algorithms.AES(key)
size = algorithm.block_size // 8
iv, encrypted = iv_ciphertext[:size], iv_ciphertext[size:]
cipher = Cipher(algorithm, modes.CFB(iv), backend=backend)
decryptor = cipher.decryptor()
return decryptor.update(encrypted) + decryptor.finalize()
This lacks the added armoring of an HMAC signature and there is no timestamp; you‚Äôd have to add those yourself.
The above also illustrates how easy it is to combine basic cryptography building blocks incorrectly; All –Ü—ï V–∞–∏—ñ—Çy‚Äòs incorrect handling of the IV value can lead to a data breach or all encrypted messages being unreadable because the IV is lost. Using Fernet instead protects you from such mistakes.
If you previously implemented AES ECB encryption and need to still support this in Python 3, you can do so still with cryptography
too. The same caveats apply, ECB is not secure enough for reallife applications. Reimplementing that answer for Python 3, adding automatic handling of padding:
from base64 import urlsafe_b64encode as b64e, urlsafe_b64decode as b64d
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
backend = default_backend()
def aes_ecb_encrypt(message, key):
cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=backend)
encryptor = cipher.encryptor()
padder = padding.PKCS7(cipher.algorithm.block_size).padder()
padded = padder.update(msg_text.encode()) + padder.finalize()
return b64e(encryptor.update(padded) + encryptor.finalize())
def aes_ecb_decrypt(ciphertext, key):
cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=backend)
decryptor = cipher.decryptor()
unpadder = padding.PKCS7(cipher.algorithm.block_size).unpadder()
padded = decryptor.update(b64d(ciphertext)) + decryptor.finalize()
return unpadder.update(padded) + unpadder.finalize()
Again, this lacks the HMAC signature, and you shouldn‚Äôt use ECB anyway. The above is there merely to illustrate that cryptography
can handle the common cryptographic building blocks, even the ones you shouldn‚Äôt actually use.
import matplotlib.pyplot as plt
circle1 = plt.Circle((0, 0), 0.2, color="r")
plt.gca().add_patch(circle1)
A quick condensed version of the accepted answer, to quickly plug a circle into an existing plot. Refer to the accepted answer and other answers to understand the details.
By the way:
gca()
means Get Current AxisThere is a picture show all markers" name and description, i hope it will help you.
import matplotlib.pylab as plt
markers = [".",",","o","v","^","<",">","1","2","3","4","8","s","p","P","*","h","H","+","x","X","D","d","","_"]
descriptions = ["point", "pixel", "circle", "triangle_down", "triangle_up","triangle_left",
"triangle_right", "tri_down", "tri_up", "tri_left", "tri_right", "octagon",
"square", "pentagon", "plus (filled)","star", "hexagon1", "hexagon2", "plus",
"x", "x (filled)","diamond", "thin_diamond", "vline", "hline"]
x=[]
y=[]
for i in range(5):
for j in range(5):
x.append(i)
y.append(j)
plt.figure(figsize=(8, 8))
for i,j,m,l in zip(x,y,markers,descriptions):
plt.scatter(i,j,marker=m)
plt.text(i0.15,j+0.15,s=m+" : "+l)
plt.axis([0.1,4.8,0.1,4.5])
plt.axis("off")
plt.tight_layout()
plt.show()
By definition, isdecimal()
‚äÜ isdigit()
‚äÜ isnumeric()
. That is, if a string is decimal
, then it"ll also be digit
and numeric
.
Therefore, given a string s
and test it with those three methods, there"ll only be 4 types of results.
+++++
 isdecimal()  isdigit()  isnumeric()  Example 
+++++
 True  True  True  "038", "‡©¶‡©©‡©Æ", "ÔºêÔºìÔºò" 
 False  True  True  "‚Å∞¬≥‚Å∏", "üÑÄ‚íä‚íè", "‚ì™‚ë¢‚ëß" 
 False  False  True  "‚Üâ‚Öõ‚Öò", "‚Ö†‚Ö¢‚Öß", "‚ë©‚ë¨„äø", "Â£πË≤≥ÂèÉ" 
 False  False  False  "abc", "38.0", "38" 
+++++
1. Some examples of characters isdecimal()==True
(thus isdigit()==True
and isnumeric()==True
)
"0123456789" DIGIT ZERO~NINE
"Ÿ†Ÿ°Ÿ¢Ÿ£Ÿ§Ÿ•Ÿ¶ŸßŸ®Ÿ©" ARABICINDIC DIGIT ZERO~NINE
"‡•¶‡•ß‡•®‡•©‡•™‡•´‡•¨‡•≠‡•Æ‡•Ø" DEVANAGARI DIGIT ZERO~NINE
"‡ß¶‡ßß‡ß®‡ß©‡ß™‡ß´‡ß¨‡ß≠‡ßÆ‡ßØ" BENGALI DIGIT ZERO~NINE
"‡©¶‡©ß‡©®‡©©‡©™‡©´‡©¨‡©≠‡©Æ‡©Ø" GURMUKHI DIGIT ZERO~NINE
"‡´¶‡´ß‡´®‡´©‡´™‡´´‡´¨‡´≠‡´Æ‡´Ø" GUJARATI DIGIT ZERO~NINE
"‡≠¶‡≠ß‡≠®‡≠©‡≠™‡≠´‡≠¨‡≠≠‡≠Æ‡≠Ø" ORIYA DIGIT ZERO~NINE
"‡Ø¶‡Øß‡Ø®‡Ø©‡Ø™‡Ø´‡Ø¨‡Ø≠‡ØÆ‡ØØ" TAMIL DIGIT ZERO~NINE
"‡±¶‡±ß‡±®‡±©‡±™‡±´‡±¨‡±≠‡±Æ‡±Ø" TELUGU DIGIT ZERO~NINE
"‡≥¶‡≥ß‡≥®‡≥©‡≥™‡≥´‡≥¨‡≥≠‡≥Æ‡≥Ø" KANNADA DIGIT ZERO~NINE
"‡µ¶‡µß‡µ®‡µ©‡µ™‡µ´‡µ¨‡µ≠‡µÆ‡µØ" MALAYALAM DIGIT ZERO~NINE
"‡πê‡πë‡πí‡πì‡πî‡πï‡πñ‡πó‡πò‡πô" THAI DIGIT ZERO~NINE
"‡ªê‡ªë‡ªí‡ªì‡ªî‡ªï‡ªñ‡ªó‡ªò‡ªô" LAO DIGIT ZERO~NINE
"‡º†‡º°‡º¢‡º£‡º§‡º•‡º¶‡ºß‡º®‡º©" TIBETAN DIGIT ZERO~NINE
"·ÅÄ·ÅÅ·ÅÇ·ÅÉ·ÅÑ·ÅÖ·ÅÜ·Åá·Åà·Åâ" MYANMAR DIGIT ZERO~NINE
"·ü†·ü°·ü¢·ü£·ü§·ü•·ü¶·üß·ü®·ü©" KHMER DIGIT ZERO~NINE
"ÔºêÔºëÔºíÔºìÔºîÔºïÔºñÔºóÔºòÔºô" FULLWIDTH DIGIT ZERO~NINE
"ùüéùüèùüêùüëùüíùüìùüîùüïùüñùüó" MATHEMATICAL BOLD DIGIT ZERO~NINE
"ùüòùüôùüöùüõùüúùüùùüûùüüùü†ùü°" MATHEMATICAL DOUBLESTRUCK DIGIT ZERO~NINE
"ùü¢ùü£ùü§ùü•ùü¶ùüßùü®ùü©ùü™ùü´" MATHEMATICAL SANSSERIF DIGIT ZERO~NINE
"ùü¨ùü≠ùüÆùüØùü∞ùü±ùü≤ùü≥ùü¥ùüµ" MATHEMATICAL SANSSERIF BOLD DIGIT ZERO~NINE
"ùü∂ùü∑ùü∏ùüπùü∫ùüªùüºùüΩùüæùüø" MATHEMATICAL MONOSPACE DIGIT ZERO~NINE
2. Some examples of characters isdecimal()==False
but isdigit()==True
(thus isnumeric()==True
)
"‚Å∞¬π¬≤¬≥‚Å¥‚Åµ‚Å∂‚Å∑‚Å∏‚Åπ" SUPERSCRIPT ZERO~NINE
"‚ÇÄ‚ÇÅ‚ÇÇ‚ÇÉ‚ÇÑ‚ÇÖ‚ÇÜ‚Çá‚Çà‚Çâ" SUBSCRIPT ZERO~NINE
"üÑÄ‚íà‚íâ‚íä‚íã‚íå‚íç‚íé‚íè‚íê" DIGIT ZERO~NINE FULL STOP
"üÑÅüÑÇüÑÉüÑÑüÑÖüÑÜüÑáüÑàüÑâüÑä" DIGIT ZERO~NINE COMMA
"‚ì™‚ë†‚ë°‚ë¢‚ë£‚ë§‚ë•‚ë¶‚ëß‚ë®" CIRCLED DIGIT ZERO~NINE
"‚ìø‚ù∂‚ù∑‚ù∏‚ùπ‚ù∫‚ùª‚ùº‚ùΩ‚ùæ" NEGATIVE CIRCLED DIGIT ZERO~NINE
"‚ë¥‚ëµ‚ë∂‚ë∑‚ë∏‚ëπ‚ë∫‚ëª‚ëº" PARENTHESIZED DIGIT ONE~NINE
"‚ûÄ‚ûÅ‚ûÇ‚ûÉ‚ûÑ‚ûÖ‚ûÜ‚ûá‚ûà" DINGBAT CIRCLED SANSSERIF DIGIT ONE~NINE
"‚ìµ‚ì∂‚ì∑‚ì∏‚ìπ‚ì∫‚ìª‚ìº‚ìΩ" DOUBLE CIRCLED DIGIT ONE~NINE
"‚ûä‚ûã‚ûå‚ûç‚ûé‚ûè‚ûê‚ûë‚ûí" DINGBAT NEGATIVE CIRCLED SANSSERIF DIGIT ONE~NINE
"·ç©·ç™·ç´·ç¨·ç≠·çÆ·çØ·ç∞·ç±" ETHIOPIC DIGIT ONE~NINE
3. Some examples of characters isdecimal()==False
and isdigit()==False
but isnumeric()==True
"¬Ω‚Öì¬º‚Öï‚Öô‚Öê‚Öõ‚Öë‚Öí‚Öî¬æ‚Öñ‚Öó‚Öò‚Öö‚Öú‚Öù‚Öû‚Öü‚Üâ" VULGAR FRACTION
"‡ß¥‡ßµ‡ß∂‡ß∑‡ß∏‡ßπ" BENGALI CURRENCY NUMERATOR
"‡Ø∞‡Ø±‡Ø≤" TAMIL NUMBER TEN, ONE HUNDRED, ONE THOUSAND
"‡±∏‡±π‡±∫‡±ª‡±º‡±Ω‡±æ" TELUGU FRACTION DIGIT
"‡µ∞‡µ±‡µ≤‡µ≥‡µ¥‡µµ" MALAYALAM NUMBER, MALAYALAM FRACTION
"‡º≥‡º™‡º´‡º¨‡º≠‡ºÆ‡ºØ‡º∞‡º±‡º≤" TIBETAN DIGIT HALF ZERO~NINE
"·ç≤·ç≥·ç¥·çµ·ç∂·ç∑·ç∏·çπ·ç∫·çª·çº" ETHIOPIC NUMBER TEN~NINETY, HUNDRED, TEN THOUSAND
"·ü∞·ü±·ü≤·ü≥·ü¥·üµ·ü∂·ü∑·ü∏·üπ" KHMER SYMBOL LEK ATTAK
"‚Ö†‚Ö°‚Ö¢‚Ö£‚Ö§‚Ö•‚Ö¶‚Öß‚Ö®‚Ö©‚Ö™‚Ö´‚Ö¨‚Ö≠‚ÖÆ‚ÖØ" ROMAN NUMERAL
"‚Ö∞‚Ö±‚Ö≤‚Ö≥‚Ö¥‚Öµ‚Ö∂‚Ö∑‚Ö∏‚Öπ‚Ö∫‚Öª‚Öº‚ÖΩ‚Öæ‚Öø" SMALL ROMAN NUMERAL
"‚ÜÄ‚ÜÅ‚ÜÇ‚ÜÖ‚ÜÜ" ROMAN NUMERAL
"‚ë©‚ë™‚ë´‚ë¨‚ë≠‚ëÆ‚ëØ‚ë∞‚ë±‚ë≤‚ë≥„âë„âí„âì„âî„âï„âñ„âó„âò„âô„âö„âõ„âú„âù„âû„âü„ä±„ä≤„ä≥„ä¥„äµ„ä∂„ä∑„ä∏„äπ„ä∫„äª„äº„äΩ„äæ„äø" CIRCLED NUMBER TEN~FIFTY
"„âà„ââ„âä„âã„âå„âç„âé„âè" CIRCLED NUMBER TEN~EIGHTY ON BLACK SQUARE
"‚ëΩ‚ëæ‚ëø‚íÄ‚íÅ‚íÇ‚íÉ‚íÑ‚íÖ‚íÜ‚íá" PARENTHESIZED NUMBER TEN~TWENTY
"‚íë‚íí‚íì‚íî‚íï‚íñ‚íó‚íò‚íô‚íö‚íõ" NUMBER TEN~TWENTY FULL STOP
"‚ì´‚ì¨‚ì≠‚ìÆ‚ìØ‚ì∞‚ì±‚ì≤‚ì≥‚ì¥" NEGATIVE CIRCLED NUMBER ELEVEN
"‚ìæ‚ûâ‚ùø‚ûì" various styles of CIRCLED NUMBER TEN
"üÑå" DINGBAT NEGATIVE CIRCLED SANSSERIF DIGIT ZERO
"„Äá" IDEOGRAPHIC NUMBER ZERO
"„Ä°„Ä¢„Ä£„Ä§„Ä•„Ä¶„Äß„Ä®„Ä©„Ä∏„Äπ„Ä∫" HANGZHOU NUMERAL ONE~TEN, TWENTY, THIRTY
"„Üí„Üì„Üî„Üï" IDEOGRAPHIC ANNOTATION ONE~FOUR MARK
"„à†„à°„à¢„à£„à§„à•„à¶„àß„à®„à©" PARENTHESIZED IDEOGRAPH ONE~TEN
"„äÄ„äÅ„äÇ„äÉ„äÑ„äÖ„äÜ„äá„äà„äâ" CIRCLED IDEOGRAPH ONE~TEN
"‰∏Ä‰∫å‰∏âÂõõ‰∫îÂÖ≠‰∏ÉÂÖ´‰πùÂçÅÂ£πË≤≥ÂèÉËÇÜ‰ºçÈô∏ÊüíÊçåÁéñÊãæÈõ∂ÁôæÂçÉËê¨ÂÑÑÂÖÜÂºêË≤ÆË¥∞„íÉ„≠çÊºÜ‰ªÄ„êÖÈôåÈò°‰Ω∞‰ªü‰∏á‰∫øÂπ∫ÂÖ©„†™‰∫ñÂçÑÂçÖÂçåÂªæÂªø" CJK UNIFIED IDEOGRAPH
"Ô•´Ô•≥Ô•∏Ô¶≤ÔßëÔßìÔßΩ" CJK COMPATIBILITY IDEOGRAPH
"êÑáêÑàêÑâêÑäêÑãêÑåêÑçêÑéêÑèêÑêêÑëêÑíêÑìêÑîêÑïêÑñêÑóêÑò" AEGEAN NUMBER ONE~NINE, TEN~NINETY
"êÑôêÑöêÑõêÑúêÑùêÑûêÑüêÑ†êÑ°êÑ¢êÑ£êÑ§êÑ•êÑ¶êÑßêÑ®êÑ©êÑ™" AEGEAN NUMBER ONE~NINE HUNDRED, ONE~NINE THOUSAND
"êÑ¨êÑ≠êÑÆêÑØêÑ∞êÑ±êÑ≤êÑ≥" AEGEAN NUMBER TEN~NINETY THOUSAND
"êÖÄêÖÅêÖÇêÖÉêÖÜêÖáêÖàêÖâêÖäêÖãêÖåêÖçêÖéêÖèêÖêêÖëêÖíêÖìêÖîêÖïêÖñêÖóêÖòêÖôêÖöêÖõêÖúêÖùêÖûêÖüêÖ†êÖ°êÖ¢êÖ£êÖ§êÖ•êÖ¶êÖßêÖ®êÖ©êÖ™êÖ´êÖ¨êÖ≠êÖÆêÖØêÖ∞êÖ±êÖ≤êÖ≥êÖ¥" GREEK ACROPHONIC ATTIC
"ùç†ùç°ùç¢ùç£ùç§ùç•ùç¶ùçßùç®" COUNTING ROD UNIT DIGIT ONE~NINE
"ùç©ùç™ùç´ùç¨ùç≠ùçÆùçØùç∞ùç±" COUNTING ROD TENS DIGIT ONE~NINE
@Jan Kuiken"s answer is certainly wellthought and thorough, but there are some caveats:
A much simpler approach is to annotate the last point of each plot. The point can also be circled, for emphasis. This can be accomplished with one extra line:
from matplotlib import pyplot as plt
for i, (x, y) in enumerate(samples):
plt.plot(x, y)
plt.text(x[1], y[1], "sample {i}".format(i=i))
A variant would be to use ax.annotate
.
If you are not into long explanations, see Paolo Bergantino‚Äôs answer.
To understand decorators, you must first understand that functions are objects in Python. This has important consequences. Let‚Äôs see why with a simple example :
def shout(word="yes"):
return word.capitalize()+"!"
print(shout())
# outputs : "Yes!"
# As an object, you can assign the function to a variable like any other object
scream = shout
# Notice we don"t use parentheses: we are not calling the function,
# we are putting the function "shout" into the variable "scream".
# It means you can then call "shout" from "scream":
print(scream())
# outputs : "Yes!"
# More than that, it means you can remove the old name "shout",
#¬†and the function will still be accessible from "scream"
del shout
try:
print(shout())
except NameError as e:
print(e)
#outputs: "name "shout" is not defined"
print(scream())
# outputs: "Yes!"
Keep this in mind. We‚Äôll circle back to it shortly.
Another interesting property of Python functions is they can be defined inside another function!
def talk():
# You can define a function on the fly in "talk" ...
def whisper(word="yes"):
return word.lower()+"..."
# ... and use it right away!
print(whisper())
# You call "talk", that defines "whisper" EVERY TIME you call it, then
# "whisper" is called in "talk".
talk()
# outputs:
# "yes..."
# But "whisper" DOES NOT EXIST outside "talk":
try:
print(whisper())
except NameError as e:
print(e)
#outputs : "name "whisper" is not defined"*
#Python"s functions are objects
Okay, still here? Now the fun part...
You‚Äôve seen that functions are objects. Therefore, functions:
That means that a function can return
another function.
def getTalk(kind="shout"):
# We define functions on the fly
def shout(word="yes"):
return word.capitalize()+"!"
def whisper(word="yes") :
return word.lower()+"..."
# Then we return one of them
if kind == "shout":
# We don"t use "()", we are not calling the function,
# we are returning the function object
return shout
else:
return whisper
# How do you use this strange beast?
# Get the function and assign it to a variable
talk = getTalk()
# You can see that "talk" is here a function object:
print(talk)
#outputs : <function shout at 0xb7ea817c>
# The object is the one returned by the function:
print(talk())
#outputs : Yes!
# And you can even use it directly if you feel wild:
print(getTalk("whisper")())
#outputs : yes...
There‚Äôs more!
If you can return
a function, you can pass one as a parameter:
def doSomethingBefore(func):
print("I do something before then I call the function you gave me")
print(func())
doSomethingBefore(scream)
#outputs:
#I do something before then I call the function you gave me
#Yes!
Well, you just have everything needed to understand decorators. You see, decorators are ‚Äúwrappers‚Äù, which means that they let you execute code before and after the function they decorate without modifying the function itself.
How you‚Äôd do it manually:
# A decorator is a function that expects ANOTHER function as parameter
def my_shiny_new_decorator(a_function_to_decorate):
# Inside, the decorator defines a function on the fly: the wrapper.
# This function is going to be wrapped around the original function
# so it can execute code before and after it.
def the_wrapper_around_the_original_function():
# Put here the code you want to be executed BEFORE the original function is called
print("Before the function runs")
# Call the function here (using parentheses)
a_function_to_decorate()
# Put here the code you want to be executed AFTER the original function is called
print("After the function runs")
# At this point, "a_function_to_decorate" HAS NEVER BEEN EXECUTED.
# We return the wrapper function we have just created.
# The wrapper contains the function and the code to execute before and after. It‚Äôs ready to use!
return the_wrapper_around_the_original_function
# Now imagine you create a function you don"t want to ever touch again.
def a_stand_alone_function():
print("I am a stand alone function, don"t you dare modify me")
a_stand_alone_function()
#outputs: I am a stand alone function, don"t you dare modify me
# Well, you can decorate it to extend its behavior.
# Just pass it to the decorator, it will wrap it dynamically in
# any code you want and return you a new function ready to be used:
a_stand_alone_function_decorated = my_shiny_new_decorator(a_stand_alone_function)
a_stand_alone_function_decorated()
#outputs:
#Before the function runs
#I am a stand alone function, don"t you dare modify me
#After the function runs
Now, you probably want that every time you call a_stand_alone_function
, a_stand_alone_function_decorated
is called instead. That‚Äôs easy, just overwrite a_stand_alone_function
with the function returned by my_shiny_new_decorator
:
a_stand_alone_function = my_shiny_new_decorator(a_stand_alone_function)
a_stand_alone_function()
#outputs:
#Before the function runs
#I am a stand alone function, don"t you dare modify me
#After the function runs
# That‚Äôs EXACTLY what decorators do!
The previous example, using the decorator syntax:
@my_shiny_new_decorator
def another_stand_alone_function():
print("Leave me alone")
another_stand_alone_function()
#outputs:
#Before the function runs
#Leave me alone
#After the function runs
Yes, that‚Äôs all, it‚Äôs that simple. @decorator
is just a shortcut to:
another_stand_alone_function = my_shiny_new_decorator(another_stand_alone_function)
Decorators are just a pythonic variant of the decorator design pattern. There are several classic design patterns embedded in Python to ease development (like iterators).
Of course, you can accumulate decorators:
def bread(func):
def wrapper():
print("</"""""">")
func()
print("<\______/>")
return wrapper
def ingredients(func):
def wrapper():
print("#tomatoes#")
func()
print("~salad~")
return wrapper
def sandwich(food="ham"):
print(food)
sandwich()
#outputs: ham
sandwich = bread(ingredients(sandwich))
sandwich()
#outputs:
#</"""""">
# #tomatoes#
# ham
# ~salad~
#<\______/>
Using the Python decorator syntax:
@bread
@ingredients
def sandwich(food="ham"):
print(food)
sandwich()
#outputs:
#</"""""">
# #tomatoes#
# ham
# ~salad~
#<\______/>
The order you set the decorators MATTERS:
@ingredients
@bread
def strange_sandwich(food="ham"):
print(food)
strange_sandwich()
#outputs:
##tomatoes#
#</"""""">
# ham
#<\______/>
# ~salad~
As a conclusion, you can easily see how to answer the question:
# The decorator to make it bold
def makebold(fn):
# The new function the decorator returns
def wrapper():
# Insertion of some code before and after
return "<b>" + fn() + "</b>"
return wrapper
# The decorator to make it italic
def makeitalic(fn):
# The new function the decorator returns
def wrapper():
# Insertion of some code before and after
return "<i>" + fn() + "</i>"
return wrapper
@makebold
@makeitalic
def say():
return "hello"
print(say())
#outputs: <b><i>hello</i></b>
# This is the exact equivalent to
def say():
return "hello"
say = makebold(makeitalic(say))
print(say())
#outputs: <b><i>hello</i></b>
You can now just leave happy, or burn your brain a little bit more and see advanced uses of decorators.
# It‚Äôs not black magic, you just have to let the wrapper
# pass the argument:
def a_decorator_passing_arguments(function_to_decorate):
def a_wrapper_accepting_arguments(arg1, arg2):
print("I got args! Look: {0}, {1}".format(arg1, arg2))
function_to_decorate(arg1, arg2)
return a_wrapper_accepting_arguments
# Since when you are calling the function returned by the decorator, you are
# calling the wrapper, passing arguments to the wrapper will let it pass them to
# the decorated function
@a_decorator_passing_arguments
def print_full_name(first_name, last_name):
print("My name is {0} {1}".format(first_name, last_name))
print_full_name("Peter", "Venkman")
# outputs:
#I got args! Look: Peter Venkman
#My name is Peter Venkman
One nifty thing about Python is that methods and functions are really the same. The only difference is that methods expect that their first argument is a reference to the current object (self
).
That means you can build a decorator for methods the same way! Just remember to take self
into consideration:
def method_friendly_decorator(method_to_decorate):
def wrapper(self, lie):
lie = lie  3 # very friendly, decrease age even more :)
return method_to_decorate(self, lie)
return wrapper
class Lucy(object):
def __init__(self):
self.age = 32
@method_friendly_decorator
def sayYourAge(self, lie):
print("I am {0}, what did you think?".format(self.age + lie))
l = Lucy()
l.sayYourAge(3)
#outputs: I am 26, what did you think?
If you‚Äôre making generalpurpose decoratorone you‚Äôll apply to any function or method, no matter its argumentsthen just use *args, **kwargs
:
def a_decorator_passing_arbitrary_arguments(function_to_decorate):
# The wrapper accepts any arguments
def a_wrapper_accepting_arbitrary_arguments(*args, **kwargs):
print("Do I have args?:")
print(args)
print(kwargs)
# Then you unpack the arguments, here *args, **kwargs
# If you are not familiar with unpacking, check:
# http://www.saltycrane.com/blog/2008/01/howtouseargsandkwargsinpython/
function_to_decorate(*args, **kwargs)
return a_wrapper_accepting_arbitrary_arguments
@a_decorator_passing_arbitrary_arguments
def function_with_no_argument():
print("Python is cool, no argument here.")
function_with_no_argument()
#outputs
#Do I have args?:
#()
#{}
#Python is cool, no argument here.
@a_decorator_passing_arbitrary_arguments
def function_with_arguments(a, b, c):
print(a, b, c)
function_with_arguments(1,2,3)
#outputs
#Do I have args?:
#(1, 2, 3)
#{}
#1 2 3
@a_decorator_passing_arbitrary_arguments
def function_with_named_arguments(a, b, c, platypus="Why not ?"):
print("Do {0}, {1} and {2} like platypus? {3}".format(a, b, c, platypus))
function_with_named_arguments("Bill", "Linus", "Steve", platypus="Indeed!")
#outputs
#Do I have args ? :
#("Bill", "Linus", "Steve")
#{"platypus": "Indeed!"}
#Do Bill, Linus and Steve like platypus? Indeed!
class Mary(object):
def __init__(self):
self.age = 31
@a_decorator_passing_arbitrary_arguments
def sayYourAge(self, lie=3): # You can now add a default value
print("I am {0}, what did you think?".format(self.age + lie))
m = Mary()
m.sayYourAge()
#outputs
# Do I have args?:
#(<__main__.Mary object at 0xb7d303ac>,)
#{}
#I am 28, what did you think?
Great, now what would you say about passing arguments to the decorator itself?
This can get somewhat twisted, since a decorator must accept a function as an argument. Therefore, you cannot pass the decorated function‚Äôs arguments directly to the decorator.
Before rushing to the solution, let‚Äôs write a little reminder:
# Decorators are ORDINARY functions
def my_decorator(func):
print("I am an ordinary function")
def wrapper():
print("I am function returned by the decorator")
func()
return wrapper
# Therefore, you can call it without any "@"
def lazy_function():
print("zzzzzzzz")
decorated_function = my_decorator(lazy_function)
#outputs: I am an ordinary function
# It outputs "I am an ordinary function", because that‚Äôs just what you do:
# calling a function. Nothing magic.
@my_decorator
def lazy_function():
print("zzzzzzzz")
#outputs: I am an ordinary function
It‚Äôs exactly the same. "my_decorator
" is called. So when you @my_decorator
, you are telling Python to call the function "labelled by the variable "my_decorator
"".
This is important! The label you give can point directly to the decorator‚Äîor not.
Let‚Äôs get evil. ‚ò∫
def decorator_maker():
print("I make decorators! I am executed only once: "
"when you make me create a decorator.")
def my_decorator(func):
print("I am a decorator! I am executed only when you decorate a function.")
def wrapped():
print("I am the wrapper around the decorated function. "
"I am called when you call the decorated function. "
"As the wrapper, I return the RESULT of the decorated function.")
return func()
print("As the decorator, I return the wrapped function.")
return wrapped
print("As a decorator maker, I return a decorator")
return my_decorator
# Let‚Äôs create a decorator. It‚Äôs just a new function after all.
new_decorator = decorator_maker()
#outputs:
#I make decorators! I am executed only once: when you make me create a decorator.
#As a decorator maker, I return a decorator
# Then we decorate the function
def decorated_function():
print("I am the decorated function.")
decorated_function = new_decorator(decorated_function)
#outputs:
#I am a decorator! I am executed only when you decorate a function.
#As the decorator, I return the wrapped function
# Let‚Äôs call the function:
decorated_function()
#outputs:
#I am the wrapper around the decorated function. I am called when you call the decorated function.
#As the wrapper, I return the RESULT of the decorated function.
#I am the decorated function.
No surprise here.
Let‚Äôs do EXACTLY the same thing, but skip all the pesky intermediate variables:
def decorated_function():
print("I am the decorated function.")
decorated_function = decorator_maker()(decorated_function)
#outputs:
#I make decorators! I am executed only once: when you make me create a decorator.
#As a decorator maker, I return a decorator
#I am a decorator! I am executed only when you decorate a function.
#As the decorator, I return the wrapped function.
# Finally:
decorated_function()
#outputs:
#I am the wrapper around the decorated function. I am called when you call the decorated function.
#As the wrapper, I return the RESULT of the decorated function.
#I am the decorated function.
Let‚Äôs make it even shorter:
@decorator_maker()
def decorated_function():
print("I am the decorated function.")
#outputs:
#I make decorators! I am executed only once: when you make me create a decorator.
#As a decorator maker, I return a decorator
#I am a decorator! I am executed only when you decorate a function.
#As the decorator, I return the wrapped function.
#Eventually:
decorated_function()
#outputs:
#I am the wrapper around the decorated function. I am called when you call the decorated function.
#As the wrapper, I return the RESULT of the decorated function.
#I am the decorated function.
Hey, did you see that? We used a function call with the "@
" syntax! :)
So, back to decorators with arguments. If we can use functions to generate the decorator on the fly, we can pass arguments to that function, right?
def decorator_maker_with_arguments(decorator_arg1, decorator_arg2):
print("I make decorators! And I accept arguments: {0}, {1}".format(decorator_arg1, decorator_arg2))
def my_decorator(func):
# The ability to pass arguments here is a gift from closures.
# If you are not comfortable with closures, you can assume it‚Äôs ok,
# or read: https://stackoverflow.com/questions/13857/canyouexplainclosuresastheyrelatetopython
print("I am the decorator. Somehow you passed me arguments: {0}, {1}".format(decorator_arg1, decorator_arg2))
# Don"t confuse decorator arguments and function arguments!
def wrapped(function_arg1, function_arg2) :
print("I am the wrapper around the decorated function.
"
"I can access all the variables
"
"  from the decorator: {0} {1}
"
"  from the function call: {2} {3}
"
"Then I can pass them to the decorated function"
.format(decorator_arg1, decorator_arg2,
function_arg1, function_arg2))
return func(function_arg1, function_arg2)
return wrapped
return my_decorator
@decorator_maker_with_arguments("Leonard", "Sheldon")
def decorated_function_with_arguments(function_arg1, function_arg2):
print("I am the decorated function and only knows about my arguments: {0}"
" {1}".format(function_arg1, function_arg2))
decorated_function_with_arguments("Rajesh", "Howard")
#outputs:
#I make decorators! And I accept arguments: Leonard Sheldon
#I am the decorator. Somehow you passed me arguments: Leonard Sheldon
#I am the wrapper around the decorated function.
#I can access all the variables
#  from the decorator: Leonard Sheldon
#  from the function call: Rajesh Howard
#Then I can pass them to the decorated function
#I am the decorated function and only knows about my arguments: Rajesh Howard
Here it is: a decorator with arguments. Arguments can be set as variable:
c1 = "Penny"
c2 = "Leslie"
@decorator_maker_with_arguments("Leonard", c1)
def decorated_function_with_arguments(function_arg1, function_arg2):
print("I am the decorated function and only knows about my arguments:"
" {0} {1}".format(function_arg1, function_arg2))
decorated_function_with_arguments(c2, "Howard")
#outputs:
#I make decorators! And I accept arguments: Leonard Penny
#I am the decorator. Somehow you passed me arguments: Leonard Penny
#I am the wrapper around the decorated function.
#I can access all the variables
#  from the decorator: Leonard Penny
#  from the function call: Leslie Howard
#Then I can pass them to the decorated function
#I am the decorated function and only know about my arguments: Leslie Howard
As you can see, you can pass arguments to the decorator like any function using this trick. You can even use *args, **kwargs
if you wish. But remember decorators are called only once. Just when Python imports the script. You can"t dynamically set the arguments afterwards. When you do "import x", the function is already decorated, so you can"t
change anything.
Okay, as a bonus, I"ll give you a snippet to make any decorator accept generically any argument. After all, in order to accept arguments, we created our decorator using another function.
We wrapped the decorator.
Anything else we saw recently that wrapped function?
Oh yes, decorators!
Let‚Äôs have some fun and write a decorator for the decorators:
def decorator_with_args(decorator_to_enhance):
"""
This function is supposed to be used as a decorator.
It must decorate an other function, that is intended to be used as a decorator.
Take a cup of coffee.
It will allow any decorator to accept an arbitrary number of arguments,
saving you the headache to remember how to do that every time.
"""
# We use the same trick we did to pass arguments
def decorator_maker(*args, **kwargs):
# We create on the fly a decorator that accepts only a function
# but keeps the passed arguments from the maker.
def decorator_wrapper(func):
# We return the result of the original decorator, which, after all,
# IS JUST AN ORDINARY FUNCTION (which returns a function).
# Only pitfall: the decorator must have this specific signature or it won"t work:
return decorator_to_enhance(func, *args, **kwargs)
return decorator_wrapper
return decorator_maker
It can be used as follows:
# You create the function you will use as a decorator. And stick a decorator on it :)
# Don"t forget, the signature is "decorator(func, *args, **kwargs)"
@decorator_with_args
def decorated_decorator(func, *args, **kwargs):
def wrapper(function_arg1, function_arg2):
print("Decorated with {0} {1}".format(args, kwargs))
return func(function_arg1, function_arg2)
return wrapper
# Then you decorate the functions you wish with your brand new decorated decorator.
@decorated_decorator(42, 404, 1024)
def decorated_function(function_arg1, function_arg2):
print("Hello {0} {1}".format(function_arg1, function_arg2))
decorated_function("Universe and", "everything")
#outputs:
#Decorated with (42, 404, 1024) {}
#Hello Universe and everything
# Whoooot!
I know, the last time you had this feeling, it was after listening a guy saying: "before understanding recursion, you must first understand recursion". But now, don"t you feel good about mastering this?
The functools
module was introduced in Python 2.5. It includes the function functools.wraps()
, which copies the name, module, and docstring of the decorated function to its wrapper.
(Fun fact: functools.wraps()
is a decorator! ‚ò∫)
# For debugging, the stacktrace prints you the function __name__
def foo():
print("foo")
print(foo.__name__)
#outputs: foo
# With a decorator, it gets messy
def bar(func):
def wrapper():
print("bar")
return func()
return wrapper
@bar
def foo():
print("foo")
print(foo.__name__)
#outputs: wrapper
# "functools" can help for that
import functools
def bar(func):
# We say that "wrapper", is wrapping "func"
# and the magic begins
@functools.wraps(func)
def wrapper():
print("bar")
return func()
return wrapper
@bar
def foo():
print("foo")
print(foo.__name__)
#outputs: foo
Now the big question: What can I use decorators for?
Seem cool and powerful, but a practical example would be great. Well, there are 1000 possibilities. Classic uses are extending a function behavior from an external lib (you can"t modify it), or for debugging (you don"t want to modify it because it‚Äôs temporary).
You can use them to extend several functions in a DRY‚Äôs way, like so:
def benchmark(func):
"""
A decorator that prints the time a function takes
to execute.
"""
import time
def wrapper(*args, **kwargs):
t = time.clock()
res = func(*args, **kwargs)
print("{0} {1}".format(func.__name__, time.clock()t))
return res
return wrapper
def logging(func):
"""
A decorator that logs the activity of the script.
(it actually just prints it, but it could be logging!)
"""
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
print("{0} {1} {2}".format(func.__name__, args, kwargs))
return res
return wrapper
def counter(func):
"""
A decorator that counts and prints the number of times a function has been executed
"""
def wrapper(*args, **kwargs):
wrapper.count = wrapper.count + 1
res = func(*args, **kwargs)
print("{0} has been used: {1}x".format(func.__name__, wrapper.count))
return res
wrapper.count = 0
return wrapper
@counter
@benchmark
@logging
def reverse_string(string):
return str(reversed(string))
print(reverse_string("Able was I ere I saw Elba"))
print(reverse_string("A man, a plan, a canoe, pasta, heros, rajahs, a coloratura, maps, snipe, percale, macaroni, a gag, a banana bag, a tan, a tag, a banana bag again (or a camel), a crepe, pins, Spam, a rut, a Rolo, cash, a jar, sore hats, a peon, a canal: Panama!"))
#outputs:
#reverse_string ("Able was I ere I saw Elba",) {}
#wrapper 0.0
#wrapper has been used: 1x
#ablE was I ere I saw elbA
#reverse_string ("A man, a plan, a canoe, pasta, heros, rajahs, a coloratura, maps, snipe, percale, macaroni, a gag, a banana bag, a tan, a tag, a banana bag again (or a camel), a crepe, pins, Spam, a rut, a Rolo, cash, a jar, sore hats, a peon, a canal: Panama!",) {}
#wrapper 0.0
#wrapper has been used: 2x
#!amanaP :lanac a ,noep a ,stah eros ,raj a ,hsac ,oloR a ,tur a ,mapS ,snip ,eperc a ,)lemac a ro( niaga gab ananab a ,gat a ,nat a ,gab ananab a ,gag a ,inoracam ,elacrep ,epins ,spam ,arutaroloc a ,shajar ,soreh ,atsap ,eonac a ,nalp a ,nam A
Of course the good thing with decorators is that you can use them right away on almost anything without rewriting. DRY, I said:
@counter
@benchmark
@logging
def get_random_futurama_quote():
from urllib import urlopen
result = urlopen("http://subfusion.net/cgibin/quote.pl?quote=futurama").read()
try:
value = result.split("<br><b><hr><br>")[1].split("<br><br><hr>")[0]
return value.strip()
except:
return "No, I"m ... doesn"t!"
print(get_random_futurama_quote())
print(get_random_futurama_quote())
#outputs:
#get_random_futurama_quote () {}
#wrapper 0.02
#wrapper has been used: 1x
#The laws of science be a harsh mistress.
#get_random_futurama_quote () {}
#wrapper 0.01
#wrapper has been used: 2x
#Curse you, merciful Poseidon!
Python itself provides several decorators: property
, staticmethod
, etc.
This really is a large playground.
Specify the keyword args linestyle
and/or marker
in your call to plot
.
For example, using a dashed line and blue circle markers:
plt.plot(range(10), linestyle="", marker="o", color="b")
A shortcut call for the same thing:
plt.plot(range(10), "bo")
Here is a list of the possible line and marker styles:
================ ===============================
character description
================ ===============================
 solid line style
 dashed line style
. dashdot line style
: dotted line style
. point marker
, pixel marker
o circle marker
v triangle_down marker
^ triangle_up marker
< triangle_left marker
> triangle_right marker
1 tri_down marker
2 tri_up marker
3 tri_left marker
4 tri_right marker
s square marker
p pentagon marker
* star marker
h hexagon1 marker
H hexagon2 marker
+ plus marker
x x marker
D diamond marker
d thin_diamond marker
 vline marker
_ hline marker
================ ===============================
edit: with an example of marking an arbitrary subset of points, as requested in the comments:
import numpy as np
import matplotlib.pyplot as plt
xs = np.linspace(np.pi, np.pi, 30)
ys = np.sin(xs)
markers_on = [12, 17, 18, 19]
plt.plot(xs, ys, "gD", markevery=markers_on)
plt.show()
This last example using the markevery
kwarg is possible in since 1.4+, due to the merge of this feature branch. If you are stuck on an older version of matplotlib, you can still achieve the result by overlaying a scatterplot on the line plot. See the edit history for more details.
First find the difference between the start point and the end point (here, this is more of a directed line segment, not a "line", since lines extend infinitely and don"t start at a particular point).
deltaY = P2_y  P1_y
deltaX = P2_x  P1_x
Then calculate the angle (which runs from the positive X axis at P1
to the positive Y axis at P1
).
angleInDegrees = arctan(deltaY / deltaX) * 180 / PI
But arctan
may not be ideal, because dividing the differences this way will erase the distinction needed to distinguish which quadrant the angle is in (see below). Use the following instead if your language includes an atan2
function:
angleInDegrees = atan2(deltaY, deltaX) * 180 / PI
EDIT (Feb. 22, 2017): In general, however, calling atan2(deltaY,deltaX)
just to get the proper angle for cos
and sin
may be inelegant. In those cases, you can often do the following instead:
(deltaX, deltaY)
as a vector.deltaX
and deltaY
by the vector"s length (sqrt(deltaX*deltaX+deltaY*deltaY)
), unless the length is 0.deltaX
will now be the cosine of the angle between the vector and the horizontal axis (in the direction from the positive X to the positive Y axis at P1
).deltaY
will now be the sine of that angle.EDIT (Feb. 28, 2017): Even without normalizing (deltaX, deltaY)
:
deltaX
will tell you whether the cosine described in step 3 is positive or negative.deltaY
will tell you whether the sine described in step 4 is positive or negative.deltaX
and deltaY
will tell you which quadrant the angle is in, in relation to the positive X axis at P1
:
+deltaX
, +deltaY
: 0 to 90 degrees.deltaX
, +deltaY
: 90 to 180 degrees.deltaX
, deltaY
: 180 to 270 degrees (180 to 90 degrees).+deltaX
, deltaY
: 270 to 360 degrees (90 to 0 degrees).An implementation in Python using radians (provided on July 19, 2015 by Eric Leschinski, who edited my answer):
from math import *
def angle_trunc(a):
while a < 0.0:
a += pi * 2
return a
def getAngleBetweenPoints(x_orig, y_orig, x_landmark, y_landmark):
deltaY = y_landmark  y_orig
deltaX = x_landmark  x_orig
return angle_trunc(atan2(deltaY, deltaX))
angle = getAngleBetweenPoints(5, 2, 1,4)
assert angle >= 0, "angle must be >= 0"
angle = getAngleBetweenPoints(1, 1, 2, 1)
assert angle == 0, "expecting angle to be 0"
angle = getAngleBetweenPoints(2, 1, 1, 1)
assert abs(pi  angle) <= 0.01, "expecting angle to be pi, it is: " + str(angle)
angle = getAngleBetweenPoints(2, 1, 2, 3)
assert abs(angle  pi/2) <= 0.01, "expecting angle to be pi/2, it is: " + str(angle)
angle = getAngleBetweenPoints(2, 1, 2, 0)
assert abs(angle  (pi+pi/2)) <= 0.01, "expecting angle to be pi+pi/2, it is: " + str(angle)
angle = getAngleBetweenPoints(1, 1, 2, 2)
assert abs(angle  (pi/4)) <= 0.01, "expecting angle to be pi/4, it is: " + str(angle)
angle = getAngleBetweenPoints(1, 1, 2, 2)
assert abs(angle  (pi+pi/4)) <= 0.01, "expecting angle to be pi+pi/4, it is: " + str(angle)
angle = getAngleBetweenPoints(1, 1, 1, 2)
assert abs(angle  (pi/2)) <= 0.01, "expecting angle to be pi/2, it is: " + str(angle)
All tests pass. See https://en.wikipedia.org/wiki/Unit_circle
Here"s a Python version:
from math import radians, cos, sin, asin, sqrt
def haversine(lon1, lat1, lon2, lat2):
"""
Calculate the great circle distance in kilometers between two points
on the earth (specified in decimal degrees)
"""
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
# haversine formula
dlon = lon2  lon1
dlat = lat2  lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * asin(sqrt(a))
r = 6371 # Radius of earth in kilometers. Use 3956 for miles. Determines return value units.
return c * r