Python 3.7

Címkék

Másfél évnyi fejlesztés után megjelent a népszerű pszeudo kód programozási nyelv 3.7-es változata. A kiadás tartalmaz többek között szintaktikai változtatásokat, új modulokak (contextvars és dataclasses), a breakpoint() beépített függvényt, nanoszekundum felbontású függvényeket a time modulban, CPython és C API fejlesztéseket és optimalizációkat, illetve a dict objektum immáron megőrzi az elemek sorrendjét.

Letöltés | Változtatások listája | Újdonságok

Néhány újdonság:

PEP 536: Típus-annotációk késleltetett kiértékelése

A típus-annotációkban korábban csak olyan elemeket lehetett használni, amelyek már elérhetőek voltak az adott névtérben. Az új eljárást használva a fordító sztringként tárolja el az annotációkat.


from __future__ import annotations

class C:
    @classmethod
    def from_string(cls, source: str) -> C:
        ...

    def validate_b(self, obj: B) -> bool:
        ...

class B:
    ...

PEP 557: Adat-osztályok
A népszerű attrs modul mintájára és alkotójának közreműködésével létrejött a dataclasses modul, amivel kényelmesebben hozhatók létre osztályok:


from dataclasses import dataclass

@dataclass
class Position:
    name: str
    lon: float = 0.0
    lat: float = 0.0


>>> Position('Null Island')
Position(name='Null Island', lon=0.0, lat=0.0)
>>> Position('Greenwich', lat=51.8)
Position(name='Greenwich', lon=0.0, lat=51.8)

A speciális metódusok (__init__(), __repr__(), __eq__()) ezután automatikusan létrejönnek, és az adat-osztály egy normál osztályként használható. A field() metódussal további tulajdonságok állíthatóak be az attribútumokhoz, mint például meta-adatok, default_factory függvény, bekerüljön-e az objektum hash értékébe, stb.

PEP 553: Beépített breakpoint() függvény
A debuggolást segíti az új

breakpoint()

beépített függvény, ami lényegében az

import pdb; pdb.set_trace()

sornak felel meg, azaz olyan pontokat definiál a forráskódban, ahol átléphetünk egy debuggerbe. Továbbá a PYTHONBREAKPOINT környezeti változóban megadható, hogy milyen debugger induljon el ezeknél a pontoknál, illetve 0-t beállítva ki is kapcsolhatóak a breakpoint()-ok.

-X importtime

opció: Importálási idők mérése
Néhány új, fejlesztést segítő opcióval is bővült a CLI, mint például

-X importtime

, amivel a szkriptben fellelhető importálási időkről kapható egy összesített táblázat:


$ python3.7 -X importtime my_script.py
import time: self [us] | cumulative | imported package
import time:      2607 |       2607 | _frozen_importlib_external
...
import time:       844 |      28866 |   importlib.resources
import time:       404 |      30434 | plugins

Hozzászólások

Ez egy jó összefoglaló volt, köszi! :)

-----
„Egy jó kapcsolatban a társunkat az ő dolgában kell támogatni, nem a miénkben.”
rand() a lelke mindennek! :)
Szerinted…

Fullos összefoglaló, köszi!

"illetve a dict objektum immáron megőrzi az elemek sorrendjét."
Deja Vu. Meg mernék eskudni, hogy ez van a 3.6-ban is, de talán már a 3.5ben is volt. Változott valami ekorul vagy az emlékeim rosszak?

-------------------------
Roses are red
Violets are blue
Unexpected '}' on line 32

Méretügyileg:


$ python3.5 -c 'import sys; print(sys.getsizeof({str(i):i for i in range(10000)}))'
393312
$ python3.6 -c 'import sys; print(sys.getsizeof({str(i):i for i in range(10000)}))'
295008

Sebességügyileg:


$ python3.5 -m timeit -s 'd={str(i):i for i in range(100)}' 'd["10"]; d["30"]; d["50"]; d["70"]; d["90"]'
10000000 loops, best of 3: 0.0991 usec per loop
$ python3.6 -m timeit -s 'd={str(i):i for i in range(100)}' 'd["10"]; d["30"]; d["50"]; d["70"]; d["90"]'
10000000 loops, best of 3: 0.0964 usec per loop

Szóval kb ugyanolyan gyors, de jelentősen kevesebb helyet használ a memóriában.

Pythonnal mennyire gyors a verziovaltas? Ha C++-nal van uj nyelvi feature, upgrade-elem a forditot, leforditom az ujjal, es mar hasznalhatom is. Javanal/PHP-nel meg az osszes tobbi futtatokornyezetes nyelvnel meg kell varnom mig az n+1. verzio elterjed, elotte hiaba hasznalnam, nem fog menni a celgepen. Pythonnal mennyire gyors ez a valtozas? (Linux disztrokban pl. szokott lenni kigyo alapbol)

--
If you get a good wife, you'll become happy; if you get a bad one, you'll become a philosopher. -Socrates

Bontsuk ketté a dolgot 2.x->3.x és 3-as ágon történő frissítésre. 2-es ágon sokan az utolsó 2.7-nél ragadtak le, mert nincs pénz/erőforrás/munkaerő, hogy egy régi, jól működő, nagyobb kódot átírjanak 3.x alá, sőt még 2.6-os kódok is előfordulnak a CentOS/RHEL 6-nak köszönhetően. Ez egy valódi, gyakran vitatott probléma a Python közösségen belül. Népszerű csomagok tekintetében már úgy 2-3 éve jól áll a dolog, minden jelentős csomag működik 3.x alatt vagy van ekvivalens alternatívája.

A 3-as ágon már szerintem gördülékenyebb a dolog. Windows-on aki akar, az frissít, Linuxon meg kb. ahogy a nagy LTS disztribúciókban megjelenik az új változat, úgy terjed lényegében, azaz 1-2 éves lemaradásban a legfrissebb kiadástól (nagyjából másfél évente jön egy újabb kiadás a 3.x ágban).

Általában az a mondás, hogy ha saját célra készítesz kódot, akkor használd nyugodtan a legújabb kiadást. Ha publikus csomagot készítesz, akkor meg nem árt, ha megy a legrégebbi támogatott 3.x változattal, de sok helyen láttam 3.6+-ot megkövetelő csomagokat (a 3.6-tal érkező f-sztring formázás sokak kedvenc új ficsőre lett).

Végre lett datetime.fromisoformat().

--
$ grep -c egy\$ word.list
100

Ha már amúgy is offtopic szál, jelzem fölösleges a \ a .sig -ben.

A szöveg - látszólag - egy Jujniksz rendszert futtató gépen kiadott parancs és eredménye, de a Jujniksz rendszerek parancsértelmezői az önmagukban álló $-jelet nem kezdik el speciális karakternek értelmezni, és emiatt nem kell eltakarni a jelentésüket.

Az, hogy "nem kell", az persze nem azt jelenti, hogy hiba, talán inkább felesleges túlbiztosításnak lehetne mondani.

=====
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?

Nem is tudtam, köszi! A fejemben az volt, hogy van pár karakter, amit gondolkodás nélkül védünk a shelltől, hogy eljusson a parancshoz. Az, hogy már nem ilyesmiket írok, néha abban a hitben ringat, hogy én vagyok a helikopter:

$ cat word.list | grep 'egy$' | wc -l

Eddig is sokat tanultam tőled és ez így is marad még egy jó ideig :)

--
$ grep -c egy$ word.list
100

„a Jujniksz rendszerek parancsértelmezői az önmagukban álló $-jelet nem kezdik el speciális karakternek értelmezni”

Túl sok parancsértelmezőt ugyan nem ismerek közelebbről, bash esetében így igaz, de például az általam alapértelmezettként használt fish esetében bizony el kell takarni, hiszen ott a $ változót vezet föl.


fish: Expected a variable name after this $.
grep -c egy$ word.list 
           ^

Tény persze, hogy nem olyan ismert és elterjedt, bár BSD-n is elvan. Szóval az escape-elt verzió biztosabb. :)
______________
"If you immediately know the candlelight is fire, the meal was cooked a long time ago."

Vajon melyik verziótól kezdve fogják az indentation kötelezőségét kiküszöbölni így a 21. század tájékán és vajh mikortól kezdenek el gondolni a visszafelé kompatibilitásra? Amúgy szuper nyelv amikor erre van szükség és persze, nem elégedetlenkedés :)

> Vajon melyik verziótól kezdve fogják az indentation kötelezőségét kiküszöbölni

Szerintem soha. Ez ilyen opinionated dolog, lehet nem szeretni, ez ilyen

> mikortól kezdenek el gondolni a visszafelé kompatibilitásra?

Itt mire gondolsz? A kettes ág erősen kompatibilis visszafele. Szerintem a hármason sincs olyan, ami 3.1ben még ment, most a 3.7ben meg ne menne. Az, hogy volt egy direkt deklaráltan breaking change, az egy dolog.

Az indentation alapvető nyelvi elem, ezen sosem fognak változtatni, ahogy a klasszikus Python2 vicc is mutatja:


$ python2
Python 2.7.15 (default, May  1 2018, 20:16:04) 
>>> from __future__ import braces 
  File "<stdin>", line 1
SyntaxError: not a chance

Visszafelé kompatibilitást nem tudom hogy lehetne megvalósítani úgy, hogy közben fejlődjön is a nyelv. Olyan értelemben amúgy létezik, hogy egy <3.7-es kód nagyon jó eséllyel változtatás nélkül (vagy triviális módosításokkal) megy 3.7-tel is.

> Visszafelé kompatibilitást nem tudom hogy lehetne megvalósítani úgy, hogy közben fejlődjön is a nyelv.

Javascript esetében vannak fordítók, amik lehetővé teszik, hogy régebbi parancsértelmezőn is fusson a kód, pl.:


var list = [ 1, 2, 3 ]
list.map(n => n ** 2)
var [ a, b, c ] = list

kódot átalakítja


var list = [1, 2, 3];
list.map(function (n) {
  return Math.pow(n, 2);
});
var a = list[0],
    b = list[1],
    c = list[2];

formára. Ilyen módon elég bonyolult új feature-öket is meg tudtak valósítani, pl async/await vagy generátorok.

Igen, a JavaScript esetében nagy hagyománya van az ilyen fordítóknak/transpilereknek az ezerféle környezet miatt. Pythonhoz eddig nem tudtam ilyesmiről, de most rákerestem és tényleg létezik egy projekt: https://github.com/nvbn/py-backwards Azonban a Python nincs nagyon efféle működésre felkészítve, lehetnek nem várt mellékhatások és kellemetlenségek.

Nagyon remélem, hogy soha nem engedik el az indentation függőséget. Egyszerűen felbecsülhetetlen sokat dob az olvashatosagon az hogy ránézésre meg tudsz mondani egy rakat dolgot egy kodról és nem kell túrni, hogy mi hol mibe van beleagyazva (nested) mert vizuálisan minden meg van kulonboztetve.
Ha betartod a PEP szabályokat (ebben egy ide nagy segítség), akkor nagyon frankó, olvasható kódot tudsz írni erőlködés nélkül.
-------------------------
Roses are red
Violets are blue
Unexpected '}' on line 32

C-ben mindig is mukodott. A baj talan a := miatt van, jobb lett volna, ha anno a = az ertekadas marad, es == a vizsgalat, mint a c-like nyelveknel. Es akkor nem lenne most problema. Raadasul egy csomo programozo amugy is ezt szokta meg (es szerintem tobben hasznalnak c-like nyelveket, jobb lett volna ehhez igazodni egyebkent is).

--
When you tear out a man's tongue, you are not proving him a liar, you're only telling the world that you fear what he might say. -George R.R. Martin

> jobb lett volna, ha anno a = az ertekadas marad, es == a vizsgalat

Tudomásom szerint ez így van python-ban. Az új operatorra azért volt szükség, mert egyszerre végzi a kettőt.

PEP 572 nélkül


first_num_match = re.search("[0-9]", text)
if first_num_match:
  print("First number in text: %s" % first_num_match.group(0))

PEP 572-vel


if first_num_match := re.search("[0-9]", text):
  print("First number in text: %s" % first_num_match.group(0))

Tehát vizsgálja, hogy a search eredményt ad vissza és ebben az esetben a visszatérési értéket el is tárolja.

Tudtommal C-ben nincs ilyen

Tudtommal C-ben nincs ilyen

Hogy a fenébe ne lenne?!? Az értékadó operátorok (=, += és társaik) mind egyúttal kifejezésként is használhatóak, és az értékadás eredménye lesz a kifejezés értéke.

#include <stdio.h>

int main(int argc, char **argv)
{
int a;
int s = 3;
printf("%d\n", a = 2+3);
printf("%d\n", s += 4);
return 0;
}

Ez pl. azt fogja mondani, hogy 5 és 7.

jogos, még a pep 572 doksija is megemlíti:

> Why not just turn existing assignment into an expression?
> C and its derivatives define the = operator as an expression, rather than a statement as is Python's way. This allows assignments in more contexts, including contexts where comparisons are more common. The syntactic similarity between if (x == y) and if (x = y) belies their drastically different semantics. Thus this proposal uses := to clarify the distinction.

A sima = szerintem is rosszabb lett volna. (így legalább a linter tud szólni, ha elírás van)

Én egyszerűen kihagytam volna a nyelvből, mert egyelőre úgy látom, hogy nem jár annyi előnnyel, hogy megérje a plusz operátor bevezetése. (bár a

white True:

kódok lecserélése elég jól hangzik)

Azt azért érdemes megjegyezni, hogy GvR nem egyedül döntött a feature bevezetéséről, hanem egy fél éves vita előzte azt meg.