l = lambda a, b: a + b print l(4, 5) res = sorted([4, -5, 1, -2, -8, 7], cmp=lambda x, y: abs(y) - abs(x)) print resWynik:
9 [-8, 7, -5, 4, -2, 1]
ekstaza, geniusz, przebłysk, olśnienie, półprawdy, półśrodki, przemilczenia, zaćmienia, głupstwa, kłamstewka, oszustwa, hultajstwo, wyrachowanie, nieprawda, nieobiektywność, niepodważalna prawda, nierówność, nieomylność, słuszność, perfekcja, krnąbrność ... niegodziwość
l = lambda a, b: a + b print l(4, 5) res = sorted([4, -5, 1, -2, -8, 7], cmp=lambda x, y: abs(y) - abs(x)) print resWynik:
9 [-8, 7, -5, 4, -2, 1]
gen_expression = (val for val in [1, 2, 3, 4, 7] if val % 2)
try:
print gen_expression.next()
print next(gen_expression)
print gen_expression.next()
print gen_expression.next()
except StopIteration:
print 'Dostalem wyjatek'
Wynik:1 3 7 Dostalem wyjatekDrugim rodzajem generatora jest generator function, który wygląda jak zwykła funkcja. Pozwala jednak na korzystanie mechanizmu yield. W momencie, gdy metoda trafi na takie miejsce, jej działanie jest przerywane i zwracana jest kontrola do naszej części kodu.
def gen_fun(arg = 1):
num = 0
yield num
while True:
num += arg
yield num
yield -num
# Zwraca generator object
g = gen_fun()
print [g.next() for _ in xrange(15)]
Wynik:[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7]Możemy również przekazać jakąś wartość do wnętrza generatora. W tym celu należy skorzystać z metody send(), które tak jak next() wznawia jego działanie. Jeżeli na takim generatorze zawołamy tylko next(), do środka przekazana zostanie wartość None.
def gen():
arg = 1
num = 0
while True:
num += arg
a = yield num
if a is not None:
arg = a
g = gen()
print g.next()
print g.next()
print g.send(100)
print g.next()
Wynik:1 2 102 202
#include <iostream>
#include <string>
using namespace std;
int main()
{
for (const auto& ch : string("rozciaganie"))
cout << ch << " ";
cout << endl;
return 0;
}
Wynik:r o z c i a g a n i e
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v = {1, 2, 4, 6};
auto vit = v.begin();
cout << *vit << endl;
return 0;
}
Drugim ficzerem jest detekcja typu przy pomocy decltype. Na podstawie zadanej zmiennej lub wyrażenia odgaduje typ, który będzie nadany nowej zmiennej. W przypadku wyrażenie, nie dochodzi do ewaluacji, wyciągany jest jedynie zwracany typ. Warto też pamiętać, że jeżeli wsadzimy do decltype zmienną i ujmiemy ją w dodatkowe nawiasy, typ który dostaniemy zawsze będzie referencją, a nowa zmienna będzie musiała być zainicjalizowana. Jeżeli natomiast z nawiasów nie skorzystamy to referencję uzyskamy tylko, gdy sama zmienna będzie typem referencyjnym.#include <iostream>
#include <vector>
#include <list>
#include <boost/type_index.hpp>
using namespace std;
list<double>::iterator get_it(list<double> l)
{
return l.begin();
}
int main()
{
list<double> l = {7.1, 2.3, 4.6};
decltype(get_it(l)) it = get_it(l); // list<double>::iterator it = get_it(l);
cout << boost::typeindex::type_id_with_cvr<decltype(it)>().pretty_name() << " " << *it << endl;
int i = 879;
decltype((i)) var1 = i; // int& var1 = i;
cout << boost::typeindex::type_id_with_cvr<decltype(var1)>().pretty_name() << " " << var1 << endl;
int& j = i;
decltype(j) var2 = i; // int& var2 = i;
cout << boost::typeindex::type_id_with_cvr<decltype(var2)>().pretty_name() << " " << var2 << endl;
decltype(i) br = 54; // int br = 54;
cout << boost::typeindex::type_id_with_cvr<decltype(br)>().pretty_name() << " " << br << endl;
return 0;
}
Wyniki:std::_List_iterator<double> 7.1 int& 879 int& 879 int 54
int i, *ip = nullptr; // i jest typu int, ip jest wskaźnikiem na int.
int* p1, p2; // p1 jest wskaźnikiem na int, p2 jest typu int.
int* a, &b = *ip; // a jest wskaźnikiem na int, b jest referencją na wartość
// wskazywaną przez ip.
A teraz trochę o const. Zawsze jest to dla mnie mylące, przynajmniej po dłuższym okresie czasu, gdy wiedza powolutku wyparowuje.const int c = 8; // c jest stałą typu int, jego wartość nie może być zmieniona.
const int &r = c; // ok, referencja na stały obiekt typu int - mówimy co będziemy mogli
// robić przy pomocy referencji - odwołując się do r nie damy rady
// zmodyfikować c (chociaż sam w sobie nie jest const).
int &r2 = c; // error, referencja na niestały obiekt.
Nie ma czegoś takiego jak stałe referencje (z technicznego punktu widzenia), są tylko referencje na stałe. Ponieważ nie można zmusić referencji by wskazywała na inny obiekt w jakimś sensie wszystkie referencje są stałe.double dval = 3.14; const double *pt = &dval; // ok (tak jak wyżej), ale nie możemy zmieniać dval, przy pomocy ptA teraz co powstanie, gdy const znajdzie się w różnych miejscach? Pewne oznaczenia - cytując za książką:
Używamy terminu top-level const do oznaczenia, że sam wskaźnik jest stały. Kiedy wskaźnik może wskazywać na stały obiekt, odnosimy się do tego jako low-level const
int i = 0;
const int c1 = 88; // c1 jest stałym obiektem typu int
int const c2 = 99; // (TO SAMO) c2 jest stałym obiektem typu int
int *const p1 = &i; // p1 jest stałym wskaźnikiem na obiekt typu int (top-level const).
const int ci = 42; // ci jest stałym obiektem typu int (top-level const).
const int *p2 = &ci; // p2 jest wskaźnikiem na stały obiekt typu int (low-level).
int const *p3 = &ci; // (TO SAMO) p3 jest wskaźnikiem na stały obiekt typu int.
const int *const p4 = p2; // p3 jest stałym wskaźnikiem na stały obiekt typu int
// (prawy const jest top-level; lewy nie)
const int &r = i; // referencja na stały obiekt typu int.
// const w typach referencyjnych zawsze jest low-level.
W odróżnieniu od referencji, wskaźniki są obiektami, więc mogą być const, co znaczy, że po ustawieniu w momencie inicjalizacji nie mogą na nic innego wskazywać. #include <iostream>
#include <stdio.h>
using namespace std;
constexpr int get_size()
{
return 6;
}
int main()
{
constexpr int sz = get_size() + 80; // ok, pod warunkiem, że funkcja też jest constexpr.
printf("%d", sz);
return 0;
}
I podgląd tego co wyprodukował kompilator (g++ -std=c++17 -S -masm=intel main.cpp). Jak widać w pliku binarnym pojawia się już obliczona wartość (80+6=86).main:
.LFB1824:
.cfi_startproc
endbr64
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
sub rsp, 16
mov DWORD PTR -4[rbp], 86
mov esi, 86
lea rdi, .LC0[rip]
mov eax, 0
call printf@PLT
mov eax, 0
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc