mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2025-08-13 10:14:58 +02:00
Merge branch 'master' of github.com:adambard/learnxinyminutes-docs
This commit is contained in:
@@ -8,6 +8,7 @@ contributors:
|
|||||||
- ["Denis Arh", "https://github.com/darh"]
|
- ["Denis Arh", "https://github.com/darh"]
|
||||||
- ["akirahirose", "https://twitter.com/akirahirose"]
|
- ["akirahirose", "https://twitter.com/akirahirose"]
|
||||||
- ["Anton Strömkvist", "http://lutic.org/"]
|
- ["Anton Strömkvist", "http://lutic.org/"]
|
||||||
|
- ["Rahil Momin", "https://github.com/iamrahil"]
|
||||||
filename: LearnBash.sh
|
filename: LearnBash.sh
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -140,6 +141,12 @@ do
|
|||||||
echo "$VARIABLE"
|
echo "$VARIABLE"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Or write it the "traditional for loop" way:
|
||||||
|
for ((a=1; a <= 3; a++))
|
||||||
|
do
|
||||||
|
echo $a
|
||||||
|
done
|
||||||
|
|
||||||
# They can also be used to act on files..
|
# They can also be used to act on files..
|
||||||
# This will run the command 'cat' on file1 and file2
|
# This will run the command 'cat' on file1 and file2
|
||||||
for VARIABLE in file1 file2
|
for VARIABLE in file1 file2
|
||||||
|
349
c++.html.markdown
Normal file
349
c++.html.markdown
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
---
|
||||||
|
language: c++
|
||||||
|
filename: learncpp.cpp
|
||||||
|
contributors:
|
||||||
|
- ["Steven Basart", "http://github.com/xksteven"]
|
||||||
|
lang: en
|
||||||
|
---
|
||||||
|
|
||||||
|
I am writing this to highlight the differences and
|
||||||
|
additions that C++ has with respect to C. My
|
||||||
|
suggestion would be to follow the C tutorial first
|
||||||
|
then look here for the additions and differences.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
///////////////////////////////////////
|
||||||
|
// C++ differences
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//In C++
|
||||||
|
//cannot use void main()
|
||||||
|
int main() { //or int main(int argc, char **argv)
|
||||||
|
//cannot end with return;
|
||||||
|
return 0;
|
||||||
|
//Can also end without return statement
|
||||||
|
}
|
||||||
|
|
||||||
|
//In C++
|
||||||
|
/*
|
||||||
|
//This could lead to compiler errors and is discouraged
|
||||||
|
//#if 0 #endif pairs are encouraged instead
|
||||||
|
*/
|
||||||
|
|
||||||
|
//In C++
|
||||||
|
sizeof(10) //Typically 4
|
||||||
|
sizeof('c') == 1
|
||||||
|
|
||||||
|
//In C
|
||||||
|
sizeof('c') == sizeof(10) //true chars are passed as ints
|
||||||
|
|
||||||
|
|
||||||
|
//In C++ strict prototyping
|
||||||
|
void func(); //function which accepts no arguments
|
||||||
|
|
||||||
|
//In C
|
||||||
|
void func(); //function which may accept arguments
|
||||||
|
|
||||||
|
|
||||||
|
//In C++
|
||||||
|
for(int i = 0; i < 10; i++) {;}
|
||||||
|
//In C must int i must be declared before
|
||||||
|
|
||||||
|
|
||||||
|
//C++ Supports Function overloading
|
||||||
|
//Provided each function takes different
|
||||||
|
//parameters
|
||||||
|
|
||||||
|
void printing(char const *myString)
|
||||||
|
{printf("String %s\n",myString);} //Hello
|
||||||
|
|
||||||
|
void printing(int myInt)
|
||||||
|
{printf("My int is %d",myInt);} //15
|
||||||
|
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
printing("Hello");
|
||||||
|
printing(15);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//C++ Default Function Arguments
|
||||||
|
void two_ints(int a = 1, int b = 4);
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
two_ints(); // arguments: 1, 4
|
||||||
|
two_ints(20); // arguments: 20, 4
|
||||||
|
two_ints(20, 5); // arguments: 20, 5
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//C++ added the nullptr which is different from 0
|
||||||
|
int *ip = nullptr; // OK
|
||||||
|
int value = nullptr; // error: value is no pointer
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// C++ Additions ontop of C
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// C++ Namespace
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
//Namespaces allow you to define your own
|
||||||
|
//functions and variables for use
|
||||||
|
|
||||||
|
// Use '::' to change variable (or function) scope
|
||||||
|
// Putting '::' before a function or variable will
|
||||||
|
// reference a global scope
|
||||||
|
|
||||||
|
// This allows you to make normal c library calls
|
||||||
|
// std is for standard library
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int counter = 50; // global variable
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
for (int counter = 1; // this refers to the
|
||||||
|
counter < 2; // local variable
|
||||||
|
counter++)
|
||||||
|
{
|
||||||
|
printf("Global var %d local var %d\n",
|
||||||
|
::counter, // global variable
|
||||||
|
counter); // local variable
|
||||||
|
// => Global var 50 local var 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Namespaces can be nested
|
||||||
|
|
||||||
|
|
||||||
|
namespace myFirstNameSpace
|
||||||
|
{
|
||||||
|
namespace myInnerSoul
|
||||||
|
{
|
||||||
|
cos(int x)
|
||||||
|
{
|
||||||
|
printf("My inner soul was made to program.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace anotherNameSpace
|
||||||
|
{
|
||||||
|
cos(int x) {;} //does nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
//Specify the full path because main is outside of both namespaces.
|
||||||
|
//Will print out My inner soul was made to program.
|
||||||
|
myFirstNameSpace::myInnerSoul::cos(60);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// C++ Strings
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
//Strings in C++ are Objects and have many functions
|
||||||
|
myString = "Hello";
|
||||||
|
myOtherString = " World";
|
||||||
|
|
||||||
|
myString + myOtherString; // => "Hello World"
|
||||||
|
|
||||||
|
myString + ' You'; // => "Hello You"
|
||||||
|
|
||||||
|
myString != myOtherString; //True
|
||||||
|
|
||||||
|
//An example of a string method
|
||||||
|
myString.append(" Dog"); // => "Hello Dog"
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// C++ Input Output
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
//C++ input and output streams
|
||||||
|
//cin, cout, cerr, << is insertion and >> is extraction operator
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
|
int myInt;
|
||||||
|
|
||||||
|
//Prints to stdout (or terminal/screen)
|
||||||
|
cout << "Enter your fav number:\n"
|
||||||
|
//Takes in input
|
||||||
|
cin >> myInt;
|
||||||
|
|
||||||
|
//cout can also be formatted
|
||||||
|
cout << "Your fav number is " << myInt << "\n"
|
||||||
|
//Your fav number is ##
|
||||||
|
|
||||||
|
cerr << "Used for error messages"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// C++ Classes
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//First example of classes
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
//define a class
|
||||||
|
class Doggie
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
int weight;
|
||||||
|
|
||||||
|
// These are only the declarations
|
||||||
|
//Can also have private and protected
|
||||||
|
public:
|
||||||
|
//The public methods (can also include variables)
|
||||||
|
|
||||||
|
// Default constructor
|
||||||
|
Doggie();
|
||||||
|
|
||||||
|
void setName(std::string dogsName);
|
||||||
|
void setWeight(int dogsWeight);
|
||||||
|
void printDog();
|
||||||
|
|
||||||
|
//Can define functions within class declaration too
|
||||||
|
void dogBark() {std::cout << "Bark Bark\n"}
|
||||||
|
|
||||||
|
//Destructors are methods that free the allocated space
|
||||||
|
~doggieDestructor();
|
||||||
|
//if no destructor compiler defines the trivial destructor
|
||||||
|
|
||||||
|
//Classes are similar to structs and must close the } with ;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is the implementation of the class methods
|
||||||
|
// Also called the definition
|
||||||
|
void Doggie::Doggie () {
|
||||||
|
std::cout << "A doggie is born. Woof!\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Doggie::setName (std::string doggie_name) {
|
||||||
|
name = doggie_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Doggie::setWeight (int doggie_weight) {
|
||||||
|
weight = doggie_weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Doggie::printDog () {
|
||||||
|
std::cout << "Dog is " << name << " weighs" << weight << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Doggie::~doggieDestructor () {
|
||||||
|
delete[] name;
|
||||||
|
delete weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main () {
|
||||||
|
Doggie deedee; // prints out a doggie is born. Woof!
|
||||||
|
deedee.setName ("Barkley");
|
||||||
|
deedee.setWeight(1000000);
|
||||||
|
deedee.printDog;
|
||||||
|
//prints => Dog is Barkley weighs 1000000
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//C++ Class inheritance
|
||||||
|
|
||||||
|
class German_Sheperd
|
||||||
|
{
|
||||||
|
//This class now inherits everything public and protected from Doggie class
|
||||||
|
Doggie d_dog;
|
||||||
|
|
||||||
|
//Good practice to put d_ in front of datatypes in classes
|
||||||
|
std::string d_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void dogType() {d_type = "German Sheperd";}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// C++ Exception Handling
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
try {
|
||||||
|
throw 12.25; // throws a double no handler declared
|
||||||
|
} catch (int errorNum)
|
||||||
|
{
|
||||||
|
std::cout << "I caught an int " << errorNum << "\n";
|
||||||
|
//default catcher
|
||||||
|
} catch (...)
|
||||||
|
{
|
||||||
|
std::cout << "I got an error. Not sure what but I can pass it up.";
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// C++ Operator Overloading
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
// In C++ you can overload operators such as +, -, new, etc.
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class Vector {
|
||||||
|
public:
|
||||||
|
double x,y;
|
||||||
|
Vector () {};
|
||||||
|
Vector (double a, double b) : x(a), y(b) {}
|
||||||
|
Vector operator + (const CVector&);
|
||||||
|
Vector operator += (const CVector&);
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector Vector::operator+ (const Vector& rhs)
|
||||||
|
{
|
||||||
|
Vector temp;
|
||||||
|
temp.x = x + rhs.x;
|
||||||
|
temp.y = y + rhs.y;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector Vector::operator+= (const Vector& rhs)
|
||||||
|
{
|
||||||
|
x += rhs.x;
|
||||||
|
y += rhs.y;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main () {
|
||||||
|
Vector up (0,1);
|
||||||
|
Vector right (1,0);
|
||||||
|
Vector result;
|
||||||
|
// This calls the Vector + operator
|
||||||
|
// Vector up calls the + (function) with right as its paramater
|
||||||
|
result = up + right;
|
||||||
|
// prints out => Result is upright (1,1)
|
||||||
|
cout << "Result is upright (" << result.x << ',' << result.y << ")\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
Futher Reading
|
||||||
|
|
||||||
|
for more resources see: http://www.icce.rug.nl/documents/cplusplus/
|
||||||
|
for other reference material: http://www.cplusplus.com/doc/tutorial/
|
@@ -4,6 +4,7 @@ filename: learnc.c
|
|||||||
contributors:
|
contributors:
|
||||||
- ["Adam Bard", "http://adambard.com/"]
|
- ["Adam Bard", "http://adambard.com/"]
|
||||||
- ["Árpád Goretity", "http://twitter.com/H2CO3_iOS"]
|
- ["Árpád Goretity", "http://twitter.com/H2CO3_iOS"]
|
||||||
|
- ["Jakub Trzebiatowski", "http://cbs.stgn.pl"]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -175,6 +176,9 @@ int main() {
|
|||||||
i2 * i1; // => 2
|
i2 * i1; // => 2
|
||||||
i1 / i2; // => 0 (0.5, but truncated towards 0)
|
i1 / i2; // => 0 (0.5, but truncated towards 0)
|
||||||
|
|
||||||
|
// You need to cast at least one integer to float to get a floating-point result
|
||||||
|
(float)i1 / i2 // => 0.5f
|
||||||
|
i1 / (double)i2 // => 0.5 // Same with double
|
||||||
f1 / f2; // => 0.5, plus or minus epsilon
|
f1 / f2; // => 0.5, plus or minus epsilon
|
||||||
// Floating-point numbers and calculations are not exact
|
// Floating-point numbers and calculations are not exact
|
||||||
|
|
||||||
@@ -194,9 +198,11 @@ int main() {
|
|||||||
2 >= 2; // => 1
|
2 >= 2; // => 1
|
||||||
|
|
||||||
// C is not Python - comparisons don't chain.
|
// C is not Python - comparisons don't chain.
|
||||||
// WRONG:
|
// Warning: The line below will compile, but it means `(0 < a) < 2`.
|
||||||
//int between_0_and_2 = 0 < a < 2;
|
// This expression is always true, because (0 < a) could be either 1 or 0.
|
||||||
// Correct:
|
// In this case it's 1, because (0 < 1).
|
||||||
|
int between_0_and_2 = 0 < a < 2;
|
||||||
|
// Instead use:
|
||||||
int between_0_and_2 = 0 < a && a < 2;
|
int between_0_and_2 = 0 < a && a < 2;
|
||||||
|
|
||||||
// Logic works on ints
|
// Logic works on ints
|
||||||
|
@@ -260,22 +260,22 @@ spawn(F). % <0.44.0>
|
|||||||
% For all of this to be useful we need to be able to receive messages. This is
|
% For all of this to be useful we need to be able to receive messages. This is
|
||||||
% achieved with the `receive` mechanism:
|
% achieved with the `receive` mechanism:
|
||||||
|
|
||||||
-module(caculateGeometry).
|
-module(calculateGeometry).
|
||||||
-compile(export_all).
|
-compile(export_all).
|
||||||
caculateAera() ->
|
calculateArea() ->
|
||||||
receive
|
receive
|
||||||
{rectangle, W, H} ->
|
{rectangle, W, H} ->
|
||||||
W * H;
|
W * H;
|
||||||
{circle, R} ->
|
{circle, R} ->
|
||||||
3.14 * R * R;
|
3.14 * R * R;
|
||||||
_ ->
|
_ ->
|
||||||
io:format("We can only caculate area of rectangles or circles.")
|
io:format("We can only calculate area of rectangles or circles.")
|
||||||
end.
|
end.
|
||||||
|
|
||||||
% Compile the module and create a process that evaluates `caculateAera` in the shell
|
% Compile the module and create a process that evaluates `calculateArea` in the shell
|
||||||
c(caculateGeometry).
|
c(calculateGeometry).
|
||||||
CaculateAera = spawn(caculateGeometry, caculateAera, []).
|
CalculateArea = spawn(calculateGeometry, calculateArea, []).
|
||||||
CaculateAera ! {circle, 2}. % 12.56000000000000049738
|
CalculateArea ! {circle, 2}. % 12.56000000000000049738
|
||||||
|
|
||||||
% The shell is also a process, you can use `self` to get the current pid
|
% The shell is also a process, you can use `self` to get the current pid
|
||||||
self(). % <0.41.0>
|
self(). % <0.41.0>
|
||||||
|
@@ -1,71 +0,0 @@
|
|||||||
---
|
|
||||||
category: tool
|
|
||||||
tool: tmux
|
|
||||||
contributors:
|
|
||||||
- ["kaernyk", "http://github.com/kaernyk"]
|
|
||||||
filename: LearnTmux.txt
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
tmux is a terminal multiplexer: it enables a number of terminals to be
|
|
||||||
created, accessed, and controlled from a single screen. tmux may be detached
|
|
||||||
from a screen and continue running in the background, then later reattached.
|
|
||||||
|
|
||||||
Once you feel comfortable manipulating tmux to suit your needs, I strongly
|
|
||||||
suggest you read the man pages.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
# Session Management
|
|
||||||
|
|
||||||
tmux new Create new session
|
|
||||||
-s "Session" Create named session
|
|
||||||
-n "Window" Create named Window
|
|
||||||
-c "/dir" Start in target directory
|
|
||||||
|
|
||||||
C^b $ Rename current session
|
|
||||||
C^b d Detach current session
|
|
||||||
C^b D Select session to detach
|
|
||||||
|
|
||||||
tmux attach Attach last/available session
|
|
||||||
-t "#" Attach target session
|
|
||||||
-d Detach the session from other instances
|
|
||||||
|
|
||||||
tmux ls List open sessions
|
|
||||||
C^b s Select new session for attached client interactively
|
|
||||||
|
|
||||||
kill-session Kill current session
|
|
||||||
-t "#" Kill target session
|
|
||||||
-a Kill all sessions
|
|
||||||
-a -t "#" Kill all sessions but the target
|
|
||||||
|
|
||||||
|
|
||||||
# Window Management
|
|
||||||
|
|
||||||
C^b c Create another window
|
|
||||||
C^b " Split Horizontally
|
|
||||||
C^b % Split Vertically
|
|
||||||
C^b M-(1-5) 1) Tile vertically
|
|
||||||
2) Tile horizontally
|
|
||||||
3) Tile Vertically /w large horizontal
|
|
||||||
4) Tile horizontally /w large vertical
|
|
||||||
5) Tile all windows evenly
|
|
||||||
|
|
||||||
C^b q Briefly display pane indexes
|
|
||||||
C^# Choose current window by #
|
|
||||||
C^b w Choose current window interactively
|
|
||||||
C^b n Change to next window
|
|
||||||
C^b p Change to previous window
|
|
||||||
C^b Up, Right Change to pane in selected direction
|
|
||||||
Down, left
|
|
||||||
C^b { Swap current/previous window
|
|
||||||
C^b } Swap current/next window
|
|
||||||
|
|
||||||
C^b C-Up, Right Resize in steps of one cell
|
|
||||||
Down, left
|
|
||||||
C^b M-Up, Right resize in steps of five cells
|
|
||||||
Down, left
|
|
||||||
|
|
||||||
exit or C^b x Kill the current window
|
|
||||||
```
|
|
@@ -39,7 +39,7 @@ This is an h2
|
|||||||
-------------
|
-------------
|
||||||
|
|
||||||
<!-- Simple text styles -->
|
<!-- Simple text styles -->
|
||||||
<!-- Text can be easily styled as italic, bold, or strikethrough using markdown -->
|
<!-- Text can be easily styled as italic or bold using markdown -->
|
||||||
|
|
||||||
*This text is in italics.*
|
*This text is in italics.*
|
||||||
_And so is this text._
|
_And so is this text._
|
||||||
@@ -52,7 +52,7 @@ __And so is this text.__
|
|||||||
*__And this!__*
|
*__And this!__*
|
||||||
|
|
||||||
<!-- In Github Flavored Markdown, which is used to render markdown files on
|
<!-- In Github Flavored Markdown, which is used to render markdown files on
|
||||||
Github, we also have: -->
|
Github, we also have strikethrough: -->
|
||||||
|
|
||||||
~~This text is rendered with strikethrough.~~
|
~~This text is rendered with strikethrough.~~
|
||||||
|
|
||||||
@@ -201,11 +201,11 @@ can be anything so long as they are unique. -->
|
|||||||
<!-- Images -->
|
<!-- Images -->
|
||||||
<!-- Images are done the same way as links but with an exclamation point in front! -->
|
<!-- Images are done the same way as links but with an exclamation point in front! -->
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
<!-- And reference style works as expected -->
|
<!-- And reference style works as expected -->
|
||||||
|
|
||||||
![This is the hover-text.][myimage]
|
![This is the alt-attribute.][myimage]
|
||||||
|
|
||||||
[myimage]: relative/urls/cool/image.jpg "if you need a title, it's here"
|
[myimage]: relative/urls/cool/image.jpg "if you need a title, it's here"
|
||||||
|
|
||||||
|
311
ocaml.html.markdown
Normal file
311
ocaml.html.markdown
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
---
|
||||||
|
language: OCaml
|
||||||
|
contributors:
|
||||||
|
- ["Daniil Baturin", "http://baturin.org/"]
|
||||||
|
---
|
||||||
|
|
||||||
|
OCaml is a strictly evaluated functional language with some imperative
|
||||||
|
features.
|
||||||
|
|
||||||
|
Along with StandardML and its dialects it belongs to ML language family.
|
||||||
|
Just like StandardML, there are both a compiler and an interpreter
|
||||||
|
for OCaml. The interpreter binary is normally called "ocaml" and
|
||||||
|
the compiler is "ocamlc.opt". There is also a bytecode compiler, "ocamlc",
|
||||||
|
but there are few reasons to use it.
|
||||||
|
|
||||||
|
It is strongly and statically typed, but instead of using manually written
|
||||||
|
type annotations, it infers types of expressions using Hindley-Milner algorithm.
|
||||||
|
It makes type annotations unnecessary in most cases, but can be a major
|
||||||
|
source of confusion for beginners.
|
||||||
|
|
||||||
|
When you are in the top level loop, OCaml will print the inferred type
|
||||||
|
after you enter an expression.
|
||||||
|
|
||||||
|
```
|
||||||
|
# let inc x = x + 1 ;;
|
||||||
|
val inc : int -> int = <fun>
|
||||||
|
# let a = 99 ;;
|
||||||
|
val a : int = 99
|
||||||
|
```
|
||||||
|
|
||||||
|
For a source file you can use "ocamlc -i /path/to/file.ml" command
|
||||||
|
to print all names and signatures.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cat sigtest.ml
|
||||||
|
let inc x = x + 1
|
||||||
|
let add x y = x + y
|
||||||
|
|
||||||
|
let a = 1
|
||||||
|
|
||||||
|
$ ocamlc -i ./sigtest.ml
|
||||||
|
val inc : int -> int
|
||||||
|
val add : int -> int -> int
|
||||||
|
val a : int
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that type signatures of functions of multiple arguments are
|
||||||
|
written in curried form.
|
||||||
|
|
||||||
|
```ocaml
|
||||||
|
(*** Comments ***)
|
||||||
|
|
||||||
|
(* Comments are enclosed in (* and *). It's fine to nest comments. *)
|
||||||
|
|
||||||
|
(* There are no single-line comments. *)
|
||||||
|
|
||||||
|
|
||||||
|
(*** Variables and functions ***)
|
||||||
|
|
||||||
|
(* Expressions can be separated by a double semicolon symbol, ";;".
|
||||||
|
In many cases it's redundant, but in this tutorial we use it after
|
||||||
|
every expression for easy pasting into the interpreter shell. *)
|
||||||
|
|
||||||
|
(* Variable and function declarations use "let" keyword. *)
|
||||||
|
let x = 10 ;;
|
||||||
|
|
||||||
|
(* Since OCaml compiler infers types automatically, you normally don't need to
|
||||||
|
specify argument types explicitly. However, you can do it if you want or need to. *)
|
||||||
|
let inc_int (x: int) = x + 1 ;;
|
||||||
|
|
||||||
|
(* You need to mark recursive function definitions as such with "rec" keyword. *)
|
||||||
|
let rec factorial n =
|
||||||
|
if n = 0 then 1
|
||||||
|
else factorial n * factorial (n-1)
|
||||||
|
;;
|
||||||
|
|
||||||
|
(* Function application usually doesn't need parentheses around arguments *)
|
||||||
|
let fact_5 = factorial 5 ;;
|
||||||
|
|
||||||
|
(* ...unless the argument is an expression. *)
|
||||||
|
let fact_4 = factorial (5-1) ;;
|
||||||
|
let sqr2 = sqr (-2) ;;
|
||||||
|
|
||||||
|
(* Every function must have at least one argument.
|
||||||
|
Since some funcions naturally don't take any arguments, there's
|
||||||
|
"unit" type for it that has the only one value written as "()" *)
|
||||||
|
let print_hello () = print_endline "hello world" ;;
|
||||||
|
|
||||||
|
(* Note that you must specify "()" as argument when calling it. *)
|
||||||
|
print_hello () ;;
|
||||||
|
|
||||||
|
(* Calling a function with insufficient number of arguments
|
||||||
|
does not cause an error, it produces a new function. *)
|
||||||
|
let make_inc x y = x + y ;; (* make_inc is int -> int -> int *)
|
||||||
|
let inc_2 = make_inc 2 ;; (* inc_2 is int -> int *)
|
||||||
|
inc_2 3 ;; (* Evaluates to 5 *)
|
||||||
|
|
||||||
|
(* You can use multiple expressions in function body.
|
||||||
|
The last expression becomes the return value. All other
|
||||||
|
expressions must be of the "unit" type.
|
||||||
|
This is useful when writing in imperative style, the simplest
|
||||||
|
form of it is inserting a debug print. *)
|
||||||
|
let print_and_return x =
|
||||||
|
print_endline (string_of_int x);
|
||||||
|
x
|
||||||
|
;;
|
||||||
|
|
||||||
|
(* Since OCaml is a functional language, it lacks "procedures".
|
||||||
|
Every function must return something. So functions that
|
||||||
|
do not really return anything and are called solely for their
|
||||||
|
side effects, like print_endline, return value of "unit" type. *)
|
||||||
|
|
||||||
|
|
||||||
|
(* Definitions can be chained with "let ... in" construct.
|
||||||
|
This is roughly the same to assigning values to multiple
|
||||||
|
variables before using them in expressions in imperative
|
||||||
|
languages. *)
|
||||||
|
let x = 10 in
|
||||||
|
let y = 20 in
|
||||||
|
x + y ;;
|
||||||
|
|
||||||
|
(* Alternatively you can use "let ... and ... in" construct.
|
||||||
|
This is especially useful for mutually recursive functions,
|
||||||
|
with ordinary "let .. in" the compiler will complain about
|
||||||
|
unbound values.
|
||||||
|
It's hard to come up with a meaningful but self-contained
|
||||||
|
example of mutually recursive functions, but that syntax
|
||||||
|
works for non-recursive definitions too. *)
|
||||||
|
let a = 3 and b = 4 in a * b ;;
|
||||||
|
|
||||||
|
|
||||||
|
(*** Operators ***)
|
||||||
|
|
||||||
|
(* There is little distintion between operators and functions.
|
||||||
|
Every operator can be called as a function. *)
|
||||||
|
|
||||||
|
(+) 3 4 (* Same as 3 + 4 *)
|
||||||
|
|
||||||
|
(* There's a number of built-in operators. One unusual feature is
|
||||||
|
that OCaml doesn't just refrain from any implicit conversions
|
||||||
|
between integers and floats, it also uses different operators
|
||||||
|
for floats. *)
|
||||||
|
12 + 3 ;; (* Integer addition. *)
|
||||||
|
12.0 +. 3.0 ;; (* Floating point addition. *)
|
||||||
|
|
||||||
|
12 / 3 ;; (* Integer division. *)
|
||||||
|
12.0 /. 3.0 ;; (* Floating point division. *)
|
||||||
|
5 mod 2 ;; (* Remainder. *)
|
||||||
|
|
||||||
|
(* Unary minus is a notable exception, it's polymorphic.
|
||||||
|
However, it also has "pure" integer and float forms. *)
|
||||||
|
- 3 ;; (* Polymorphic, integer *)
|
||||||
|
- 4.5 ;; (* Polymorphic, float *)
|
||||||
|
~- 3 (* Integer only *)
|
||||||
|
~- 3.4 (* Type error *)
|
||||||
|
~-. 3.4 (* Float only *)
|
||||||
|
|
||||||
|
(* You can define your own operators or redefine existing ones.
|
||||||
|
Unlike SML or Haskell, only selected symbols can be used
|
||||||
|
for operator names and first symbol defines associativity
|
||||||
|
and precedence rules. *)
|
||||||
|
let (+) a b = a - b ;; (* Surprise maintenance programmers. *)
|
||||||
|
|
||||||
|
(* More useful: a reciprocal operator for floats.
|
||||||
|
Unary operators must start with "~". *)
|
||||||
|
let (~/) x = 1.0 /. x ;;
|
||||||
|
~/4.0 (* = 0.25 *)
|
||||||
|
|
||||||
|
|
||||||
|
(*** Built-in datastructures ***)
|
||||||
|
|
||||||
|
(* Lists are enclosed in square brackets, items are separated by
|
||||||
|
semicolons. *)
|
||||||
|
let my_list = [1; 2; 3] ;;
|
||||||
|
|
||||||
|
(* Tuples are (optionally) enclosed in parentheses, items are separated
|
||||||
|
by commas. *)
|
||||||
|
let first_tuple = 3, 4 ;; (* Has type "int * int". *)
|
||||||
|
let second_tuple = (4, 5) ;;
|
||||||
|
|
||||||
|
(* Corollary: if you try to separate list items by commas, you get a list
|
||||||
|
with a tuple inside, probably not what you want. *)
|
||||||
|
let bad_list = [1, 2] ;; (* Becomes [(1, 2)] *)
|
||||||
|
|
||||||
|
(* You can access individual list items with the List.nth function. *)
|
||||||
|
List.nth my_list 1 ;;
|
||||||
|
|
||||||
|
(* You can add an item to the beginning of a list with the "::" constructor
|
||||||
|
often referred to as "cons". *)
|
||||||
|
1 :: [2; 3] ;; (* Gives [1; 2; 3] *)
|
||||||
|
|
||||||
|
(* Arrays are enclosed in [| |] *)
|
||||||
|
let my_array = [| 1; 2; 3 |] ;;
|
||||||
|
|
||||||
|
(* You can access array items like this: *)
|
||||||
|
my_array.(0) ;;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(*** User-defined data types ***)
|
||||||
|
|
||||||
|
(* You can define types with the "type some_type =" construct. Like in this
|
||||||
|
useless type alias: *)
|
||||||
|
type my_int = int ;;
|
||||||
|
|
||||||
|
(* More interesting types include so called type constructors.
|
||||||
|
Constructors must start with a capital letter. *)
|
||||||
|
type ml = OCaml | StandardML ;;
|
||||||
|
let lang = OCaml ;; (* Has type "ml". *)
|
||||||
|
|
||||||
|
(* Type constructors don't need to be empty. *)
|
||||||
|
type my_number = PlusInfinity | MinusInfinity | Real of float ;;
|
||||||
|
let r0 = Real (-3.4) ;; (* Has type "my_number". *)
|
||||||
|
|
||||||
|
(* Can be used to implement polymorphic arithmetics. *)
|
||||||
|
type number = Int of int | Float of float ;;
|
||||||
|
|
||||||
|
(* Point on a plane, essentially a type-constrained tuple *)
|
||||||
|
type point2d = Point of float * float ;;
|
||||||
|
let my_point = Point (2.0, 3.0) ;;
|
||||||
|
|
||||||
|
(* Types can be parameterized, like in this type for "list of lists
|
||||||
|
of anything". 'a can be substituted with any type. *)
|
||||||
|
type 'a list_of_lists = 'a list list ;;
|
||||||
|
type int_list_list = int list_of_lists ;;
|
||||||
|
|
||||||
|
(* Types can also be recursive. Like in this type analogous to
|
||||||
|
built-in list of integers. *)
|
||||||
|
type my_int_list = EmptyList | IntList of int * my_int_list ;;
|
||||||
|
let l = Cons (1, EmptyList) ;;
|
||||||
|
|
||||||
|
|
||||||
|
(*** Pattern matching ***)
|
||||||
|
|
||||||
|
(* Pattern matching is somewhat similar to switch statement in imperative
|
||||||
|
languages, but offers a lot more expressive power.
|
||||||
|
|
||||||
|
Even though it may look complicated, it really boils down to matching
|
||||||
|
an argument against an exact value, a predicate, or a type constructor. The type system
|
||||||
|
is what makes it so powerful. *)
|
||||||
|
|
||||||
|
(** Matching exact values. **)
|
||||||
|
|
||||||
|
let is_zero x =
|
||||||
|
match x with
|
||||||
|
| 0 -> true
|
||||||
|
| _ -> false (* The "_" pattern means "anything else". *)
|
||||||
|
;;
|
||||||
|
|
||||||
|
(* Alternatively, you can use the "function" keyword. *)
|
||||||
|
let is_one x = function
|
||||||
|
| 1 -> true
|
||||||
|
| _ -> false
|
||||||
|
;;
|
||||||
|
|
||||||
|
(* Matching predicates, aka "guarded pattern matching". *)
|
||||||
|
let abs x =
|
||||||
|
match x with
|
||||||
|
| x when x < 0 -> -x
|
||||||
|
| _ -> x
|
||||||
|
;;
|
||||||
|
|
||||||
|
abs 5 ;; (* 5 *)
|
||||||
|
abs (-5) (* 5 again *)
|
||||||
|
|
||||||
|
(** Matching type constructors **)
|
||||||
|
|
||||||
|
type animal = Dog of string | Cat of string ;;
|
||||||
|
|
||||||
|
let say x =
|
||||||
|
match x with
|
||||||
|
| Dog x -> x ^ " says woof"
|
||||||
|
| Cat x -> x ^ " says meow"
|
||||||
|
;;
|
||||||
|
|
||||||
|
say (Cat "Fluffy") ;; (* "Fluffy says meow". *)
|
||||||
|
|
||||||
|
(** Traversing datastructures with pattern matching **)
|
||||||
|
|
||||||
|
(* Recursive types can be traversed with pattern matching easily.
|
||||||
|
Let's see how we can traverse a datastructure of the built-in list type.
|
||||||
|
Even though the built-in cons ("::") looks like an infix operator, it's actually
|
||||||
|
a type constructor and can be matched like any other. *)
|
||||||
|
let rec sum_list l =
|
||||||
|
match l with
|
||||||
|
| [] -> 0
|
||||||
|
| head :: tail -> head + (sum_list tail)
|
||||||
|
;;
|
||||||
|
|
||||||
|
sum_list [1; 2; 3] ;; (* Evaluates to 6 *)
|
||||||
|
|
||||||
|
(* Built-in syntax for cons obscures the structure a bit, so we'll make
|
||||||
|
our own list for demonstration. *)
|
||||||
|
|
||||||
|
type int_list = Nil | Cons of int * int_list ;;
|
||||||
|
let rec sum_int_list l =
|
||||||
|
match l with
|
||||||
|
| Nil -> 0
|
||||||
|
| Cons (head, tail) -> head + (sum_int_list tail)
|
||||||
|
;;
|
||||||
|
|
||||||
|
let t = Cons (1, Cons (2, Cons (3, Nil))) ;;
|
||||||
|
sum_int_list t ;;
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Further reading
|
||||||
|
|
||||||
|
* Visit the official website to get the compiler and read the docs: <http://ocaml.org/>
|
||||||
|
* Try interactive tutorials and a web-based interpreter by OCaml Pro: <http://try.ocamlpro.com/>
|
||||||
|
* Read "OCaml for the skeptical" course: <http://www2.lib.uchicago.edu/keith/ocaml-class/home.html>
|
@@ -57,9 +57,17 @@ to Python 2.x. Look for another tour of Python 3 soon!
|
|||||||
# Enforce precedence with parentheses
|
# Enforce precedence with parentheses
|
||||||
(1 + 3) * 2 # => 8
|
(1 + 3) * 2 # => 8
|
||||||
|
|
||||||
# Boolean values are primitives
|
# Boolean Operators
|
||||||
True
|
+# Note "and" and "or" are case-sensitive
|
||||||
False
|
+True and False #=> False
|
||||||
|
+False or True #=> True
|
||||||
|
+
|
||||||
|
+# Note using Bool operators with ints
|
||||||
|
+0 and 2 #=> 0
|
||||||
|
+-5 or 0 #=> -5
|
||||||
|
+0 == False #=> True
|
||||||
|
+2 == True #=> False
|
||||||
|
1 == True #=> True
|
||||||
|
|
||||||
# negate with not
|
# negate with not
|
||||||
not True # => False
|
not True # => False
|
||||||
|
@@ -61,6 +61,18 @@ False
|
|||||||
not True # => False
|
not True # => False
|
||||||
not False # => True
|
not False # => True
|
||||||
|
|
||||||
|
# Boolean Operators
|
||||||
|
# Note "and" and "or" are case-sensitive
|
||||||
|
True and False #=> False
|
||||||
|
False or True #=> True
|
||||||
|
|
||||||
|
# Note using Bool operators with ints
|
||||||
|
0 and 2 #=> 0
|
||||||
|
-5 or 0 #=> -5
|
||||||
|
0 == False #=> True
|
||||||
|
2 == True #=> False
|
||||||
|
1 == True #=> True
|
||||||
|
|
||||||
# Equality is ==
|
# Equality is ==
|
||||||
1 == 1 # => True
|
1 == 1 # => True
|
||||||
2 == 1 # => False
|
2 == 1 # => False
|
||||||
@@ -127,7 +139,8 @@ bool({}) #=> False
|
|||||||
# Python has a print function
|
# Python has a print function
|
||||||
print("I'm Python. Nice to meet you!")
|
print("I'm Python. Nice to meet you!")
|
||||||
|
|
||||||
# No need to declare variables before assigning to them. Convention is to use lower_case_with_underscores
|
# No need to declare variables before assigning to them.
|
||||||
|
# Convention is to use lower_case_with_underscores
|
||||||
some_var = 5
|
some_var = 5
|
||||||
some_var # => 5
|
some_var # => 5
|
||||||
|
|
||||||
@@ -176,7 +189,8 @@ li[::-1] # => [3, 4, 2, 1]
|
|||||||
del li[2] # li is now [1, 2, 3]
|
del li[2] # li is now [1, 2, 3]
|
||||||
|
|
||||||
# You can add lists
|
# You can add lists
|
||||||
li + other_li # => [1, 2, 3, 4, 5, 6] - Note: values for li and for other_li are not modified.
|
# Note: values for li and for other_li are not modified.
|
||||||
|
li + other_li # => [1, 2, 3, 4, 5, 6]
|
||||||
|
|
||||||
# Concatenate lists with "extend()"
|
# Concatenate lists with "extend()"
|
||||||
li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6]
|
li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6]
|
||||||
@@ -215,14 +229,17 @@ filled_dict = {"one": 1, "two": 2, "three": 3}
|
|||||||
# Look up values with []
|
# Look up values with []
|
||||||
filled_dict["one"] # => 1
|
filled_dict["one"] # => 1
|
||||||
|
|
||||||
# Get all keys as a list with "keys()". We need to wrap the call in list() because we are getting back an iterable. We'll talk about those later.
|
# Get all keys as a list with "keys()".
|
||||||
list(filled_dict.keys()) # => ["three", "two", "one"]
|
# We need to wrap the call in list() because we are getting back an iterable. We'll talk about those later.
|
||||||
# Note - Dictionary key ordering is not guaranteed.
|
# Note - Dictionary key ordering is not guaranteed.
|
||||||
# Your results might not match this exactly.
|
# Your results might not match this exactly.
|
||||||
|
list(filled_dict.keys()) # => ["three", "two", "one"]
|
||||||
|
|
||||||
|
|
||||||
# Get all values as a list with "values()". Once again we need to wrap it in list() to get it out of the iterable.
|
# Get all values as a list with "values()". Once again we need to wrap it in list() to get it out of the iterable.
|
||||||
list(filled_dict.values()) # => [3, 2, 1]
|
|
||||||
# Note - Same as above regarding key ordering.
|
# Note - Same as above regarding key ordering.
|
||||||
|
list(filled_dict.values()) # => [3, 2, 1]
|
||||||
|
|
||||||
|
|
||||||
# Check for existence of keys in a dictionary with "in"
|
# Check for existence of keys in a dictionary with "in"
|
||||||
"one" in filled_dict # => True
|
"one" in filled_dict # => True
|
||||||
@@ -242,6 +259,10 @@ filled_dict.get("four", 4) # => 4
|
|||||||
filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5
|
filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5
|
||||||
filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5
|
filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5
|
||||||
|
|
||||||
|
# Adding to a dictionary
|
||||||
|
filled_dict.update({"four":4}) #=> {"one": 1, "two": 2, "three": 3, "four": 4}
|
||||||
|
#filled_dict["four"] = 4 #another way to add to dict
|
||||||
|
|
||||||
# Remove keys from a dictionary with del
|
# Remove keys from a dictionary with del
|
||||||
del filled_dict["one"] # Removes the key "one" from filled dict
|
del filled_dict["one"] # Removes the key "one" from filled dict
|
||||||
|
|
||||||
@@ -458,6 +479,7 @@ map(add_10, [1, 2, 3]) # => [11, 12, 13]
|
|||||||
filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7]
|
filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7]
|
||||||
|
|
||||||
# We can use list comprehensions for nice maps and filters
|
# We can use list comprehensions for nice maps and filters
|
||||||
|
# List comprehension stores the output as a list which can itself be a nested list
|
||||||
[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13]
|
[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13]
|
||||||
[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7]
|
[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7]
|
||||||
|
|
||||||
|
@@ -5,25 +5,29 @@ contributors:
|
|||||||
- ["Louie Dinh", "http://ldinh.ca"]
|
- ["Louie Dinh", "http://ldinh.ca"]
|
||||||
translators:
|
translators:
|
||||||
- ["Yury Timofeev", "http://twitter.com/gagar1n"]
|
- ["Yury Timofeev", "http://twitter.com/gagar1n"]
|
||||||
|
- ["Andre Polykanine", "https://github.com/Oire"]
|
||||||
filename: learnpython-ru.py
|
filename: learnpython-ru.py
|
||||||
---
|
---
|
||||||
|
|
||||||
Язык Python был создан Гвидо ван Россумом в начале 90-х. Сейчас это один из самых популярных
|
Язык Python был создан Гвидо ван Россумом в начале 90-х. Сейчас это один из
|
||||||
языков. Я люблю его за его понятный и доходчивый синтаксис - это почти что исполняемый псевдокод.
|
самых популярных языков. Я люблю его за понятный и доходчивый синтаксис — это
|
||||||
|
почти что исполняемый псевдокод.
|
||||||
|
|
||||||
С благодарностью жду ваших отзывов: [@louiedinh](http://twitter.com/louiedinh) или louiedinh [at] [google's email service]
|
С благодарностью жду ваших отзывов: [@louiedinh](http://twitter.com/louiedinh)
|
||||||
|
или louiedinh [at] [почтовый сервис Google]
|
||||||
|
|
||||||
Замечание: Эта статья относится к Python 2.7, но должно работать и в Python 2.x. Скоро будет версия и для Python 3!
|
Замечание: Эта статья относится к Python 2.7, но должно работать и в Python 2.x.
|
||||||
|
Скоро будет версия и для Python 3!
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# Однострочные комментарии начинаются с hash-символа.
|
# Однострочные комментарии начинаются с символа решётки.
|
||||||
""" Многострочный текст может быть
|
""" Многострочный текст может быть
|
||||||
записан, используя 3 знака " и обычно используется
|
записан, используя 3 знака " и обычно используется
|
||||||
в качестве комментария
|
в качестве комментария
|
||||||
"""
|
"""
|
||||||
|
|
||||||
####################################################
|
####################################################
|
||||||
## 1. Примитивные типы данных и операторов
|
## 1. Примитивные типы данных и операторы
|
||||||
####################################################
|
####################################################
|
||||||
|
|
||||||
# У вас есть числа
|
# У вас есть числа
|
||||||
@@ -36,17 +40,31 @@ filename: learnpython-ru.py
|
|||||||
35 / 5 #=> 7
|
35 / 5 #=> 7
|
||||||
|
|
||||||
# А вот деление немного сложнее. В этом случае происходит деление
|
# А вот деление немного сложнее. В этом случае происходит деление
|
||||||
# целых чисел и результат автоматически округляется в меньшую сторону.
|
# целых чисел, и результат автоматически округляется в меньшую сторону.
|
||||||
5 / 2 #=> 2
|
5 / 2 #=> 2
|
||||||
|
|
||||||
# Чтобы научиться делить, сначала нужно немного узнать о дробных числах.
|
# Чтобы научиться делить, сначала нужно немного узнать о числах
|
||||||
2.0 # Это дробное число
|
# с плавающей запятой.
|
||||||
|
2.0 # Это число с плавающей запятой
|
||||||
11.0 / 4.0 #=> 2.75 Вооот... Так гораздо лучше
|
11.0 / 4.0 #=> 2.75 Вооот... Так гораздо лучше
|
||||||
|
|
||||||
|
# Результат целочисленного деления округляется в меньшую сторону
|
||||||
|
# как для положительных, так и для отрицательных чисел.
|
||||||
|
5 // 3 # => 1
|
||||||
|
5.0 // 3.0 # => 1.0 # работает и для чисел с плавающей запятой
|
||||||
|
-5 // 3 # => -2
|
||||||
|
-5.0 // 3.0 # => -2.0
|
||||||
|
|
||||||
|
# Остаток от деления
|
||||||
|
7 % 3 # => 1
|
||||||
|
|
||||||
|
# Возведение в степень
|
||||||
|
2 ** 4 # => 16
|
||||||
|
|
||||||
# Приоритет операций указывается скобками
|
# Приоритет операций указывается скобками
|
||||||
(1 + 3) * 2 #=> 8
|
(1 + 3) * 2 #=> 8
|
||||||
|
|
||||||
# Логические значения являются примитивами
|
# Логические (булевы) значения являются примитивами
|
||||||
True
|
True
|
||||||
False
|
False
|
||||||
|
|
||||||
@@ -54,15 +72,15 @@ False
|
|||||||
not True #=> False
|
not True #=> False
|
||||||
not False #=> True
|
not False #=> True
|
||||||
|
|
||||||
# Равенство это ==
|
# Равенство — это ==
|
||||||
1 == 1 #=> True
|
1 == 1 #=> True
|
||||||
2 == 1 #=> False
|
2 == 1 #=> False
|
||||||
|
|
||||||
# Неравенство это !=
|
# Неравенство — это !=
|
||||||
1 != 1 #=> False
|
1 != 1 #=> False
|
||||||
2 != 1 #=> True
|
2 != 1 #=> True
|
||||||
|
|
||||||
# Еще немного сравнений
|
# Ещё немного сравнений
|
||||||
1 < 10 #=> True
|
1 < 10 #=> True
|
||||||
1 > 10 #=> False
|
1 > 10 #=> False
|
||||||
2 <= 2 #=> True
|
2 <= 2 #=> True
|
||||||
@@ -85,9 +103,10 @@ not False #=> True
|
|||||||
# Символ % используется для форматирования строк, например:
|
# Символ % используется для форматирования строк, например:
|
||||||
"%s могут быть %s" % ("строки", "интерполированы")
|
"%s могут быть %s" % ("строки", "интерполированы")
|
||||||
|
|
||||||
# Новый метод форматирования строк - использование метода format.
|
# Новый способ форматирования строк — использование метода format.
|
||||||
# Это предпочитаемый способ.
|
# Это предпочитаемый способ.
|
||||||
"{0} могут быть {1}".format("строки", "форматированы")
|
"{0} могут быть {1}".format("строки", "форматированы")
|
||||||
|
|
||||||
# Если вы не хотите считать, можете использовать ключевые слова.
|
# Если вы не хотите считать, можете использовать ключевые слова.
|
||||||
"{name} хочет есть {food}".format(name="Боб", food="лазанью")
|
"{name} хочет есть {food}".format(name="Боб", food="лазанью")
|
||||||
|
|
||||||
@@ -95,7 +114,7 @@ not False #=> True
|
|||||||
None #=> None
|
None #=> None
|
||||||
|
|
||||||
# Не используйте оператор равенства '=='' для сравнения
|
# Не используйте оператор равенства '=='' для сравнения
|
||||||
# объектов с None. Используйте для этого 'is'
|
# объектов с None. Используйте для этого «is»
|
||||||
"etc" is None #=> False
|
"etc" is None #=> False
|
||||||
None is None #=> True
|
None is None #=> True
|
||||||
|
|
||||||
@@ -113,17 +132,18 @@ None is None #=> True
|
|||||||
## 2. Переменные и коллекции
|
## 2. Переменные и коллекции
|
||||||
####################################################
|
####################################################
|
||||||
|
|
||||||
# Печатать довольно просто
|
# У Python есть функция Print, доступная в версиях 2.7 и 3,
|
||||||
print "Я Python. Приятно познакомиться!"
|
print("Я Python. Приятно познакомиться!")
|
||||||
|
# ...и старый оператор print, доступный в версиях 2.x, но удалённый в версии 3.
|
||||||
|
print "И я тоже Python!"
|
||||||
|
|
||||||
# Необязательно объявлять переменные перед их инициализацией.
|
# Необязательно объявлять переменные перед их инициализацией.
|
||||||
some_var = 5 # По соглашению используется нижний_регистр_с_подчеркиваниями
|
some_var = 5 # По соглашению используется нижний_регистр_с_подчёркиваниями
|
||||||
some_var #=> 5
|
some_var #=> 5
|
||||||
|
|
||||||
# При попытке доступа к неинициализированной переменной,
|
# При попытке доступа к неинициализированной переменной
|
||||||
# выбрасывается исключение.
|
# выбрасывается исключение.
|
||||||
# См. раздел "Поток управления" для информации об исключениях.
|
# См. раздел «Поток управления» для информации об исключениях.
|
||||||
some_other_var # Выбрасывает ошибку именования
|
some_other_var # Выбрасывает ошибку именования
|
||||||
|
|
||||||
# if может быть использован как выражение
|
# if может быть использован как выражение
|
||||||
@@ -149,24 +169,30 @@ li[0] #=> 1
|
|||||||
# Обратимся к последнему элементу
|
# Обратимся к последнему элементу
|
||||||
li[-1] #=> 3
|
li[-1] #=> 3
|
||||||
|
|
||||||
# Попытка выйти за границы массива приведет к IndexError
|
# Попытка выйти за границы массива приведёт к ошибке индекса
|
||||||
li[4] # Выдает IndexError
|
li[4] # Выдаёт IndexError
|
||||||
|
|
||||||
# Можно обращаться к диапазону, используя "кусочный синтаксис" (slice syntax)
|
# Можно обращаться к диапазону, используя "кусочный синтаксис" (slice syntax)
|
||||||
# (Для тех, кто любит математику, это называется замкнуто/открытый интервал.)
|
# (Для тех, кто любит математику, это называется замкнуто-открытый интервал).
|
||||||
li[1:3] #=> [2, 4]
|
li[1:3] #=> [2, 4]
|
||||||
# Опускаем начало
|
# Опускаем начало
|
||||||
li[2:] #=> [4, 3]
|
li[2:] #=> [4, 3]
|
||||||
# Опускаем конец
|
# Опускаем конец
|
||||||
li[:3] #=> [1, 2, 4]
|
li[:3] #=> [1, 2, 4]
|
||||||
|
# Выбираем каждый второй элемент
|
||||||
|
li[::2] # =>[1, 4]
|
||||||
|
# Переворачиваем список
|
||||||
|
li[::-1] # => [3, 4, 2, 1]
|
||||||
|
# Используйте сочетания всего вышеназванного для выделения более сложных кусков
|
||||||
|
# li[начало:конец:шаг]
|
||||||
|
|
||||||
# Удаляем произвольные элементы из списка оператором del
|
# Удаляем произвольные элементы из списка оператором del
|
||||||
del li[2] # [1, 2, 3]
|
del li[2] # [1, 2, 3]
|
||||||
|
|
||||||
# Вы можете складывать списки
|
# Вы можете складывать списки
|
||||||
li + other_li #=> [1, 2, 3, 4, 5, 6] - Замечание: li и other_li остаются нетронутыми
|
li + other_li #=> [1, 2, 3, 4, 5, 6] — Замечание: li и other_li не изменяются
|
||||||
|
|
||||||
# Конкатенировать списки можно методом extend
|
# Объединять списки можно методом extend
|
||||||
li.extend(other_li) # Теперь li содержит [1, 2, 3, 4, 5, 6]
|
li.extend(other_li) # Теперь li содержит [1, 2, 3, 4, 5, 6]
|
||||||
|
|
||||||
# Проверить элемент на вхождение в список можно оператором in
|
# Проверить элемент на вхождение в список можно оператором in
|
||||||
@@ -176,12 +202,12 @@ li.extend(other_li) # Теперь li содержит [1, 2, 3, 4, 5, 6]
|
|||||||
len(li) #=> 6
|
len(li) #=> 6
|
||||||
|
|
||||||
|
|
||||||
# Кортежи - это такие списки, только неизменяемые
|
# Кортежи — это такие списки, только неизменяемые
|
||||||
tup = (1, 2, 3)
|
tup = (1, 2, 3)
|
||||||
tup[0] #=> 1
|
tup[0] #=> 1
|
||||||
tup[0] = 3 # Выдает TypeError
|
tup[0] = 3 # Выдаёт TypeError
|
||||||
|
|
||||||
# Все то же самое можно делать и с кортежами
|
# Всё то же самое можно делать и с кортежами
|
||||||
len(tup) #=> 3
|
len(tup) #=> 3
|
||||||
tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6)
|
tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6)
|
||||||
tup[:2] #=> (1, 2)
|
tup[:2] #=> (1, 2)
|
||||||
@@ -203,33 +229,33 @@ filled_dict = {"one": 1, "two": 2, "three": 3}
|
|||||||
# Значения ищутся по ключу с помощью оператора []
|
# Значения ищутся по ключу с помощью оператора []
|
||||||
filled_dict["one"] #=> 1
|
filled_dict["one"] #=> 1
|
||||||
|
|
||||||
# Можно получить все ключи в виде списка
|
# Можно получить все ключи в виде списка с помощью метода keys
|
||||||
filled_dict.keys() #=> ["three", "two", "one"]
|
filled_dict.keys() #=> ["three", "two", "one"]
|
||||||
# Замечание - сохранение порядка ключей в словаре не гарантируется
|
# Замечание: сохранение порядка ключей в словаре не гарантируется
|
||||||
# Ваши результаты могут не совпадать с этими.
|
# Ваши результаты могут не совпадать с этими.
|
||||||
|
|
||||||
# Можно получить и все значения в виде списка
|
# Можно получить и все значения в виде списка, используйте метод values
|
||||||
filled_dict.values() #=> [3, 2, 1]
|
filled_dict.values() #=> [3, 2, 1]
|
||||||
# То же самое замечание насчет порядка ключей справедливо и здесь
|
# То же самое замечание насчёт порядка ключей справедливо и здесь
|
||||||
|
|
||||||
# При помощи оператора in можно проверять ключи на вхождение в словарь
|
# При помощи оператора in можно проверять ключи на вхождение в словарь
|
||||||
"one" in filled_dict #=> True
|
"one" in filled_dict #=> True
|
||||||
1 in filled_dict #=> False
|
1 in filled_dict #=> False
|
||||||
|
|
||||||
# Попытка получить значение по несуществующему ключу выбросит KeyError
|
# Попытка получить значение по несуществующему ключу выбросит ошибку ключа
|
||||||
filled_dict["four"] # KeyError
|
filled_dict["four"] # KeyError
|
||||||
|
|
||||||
# Чтобы избежать этого, используйте метод get
|
# Чтобы избежать этого, используйте метод get
|
||||||
filled_dict.get("one") #=> 1
|
filled_dict.get("one") #=> 1
|
||||||
filled_dict.get("four") #=> None
|
filled_dict.get("four") #=> None
|
||||||
# Метод get также принимает аргумент default, значение которого будет
|
# Метод get также принимает аргумент по умолчанию, значение которого будет
|
||||||
# возвращено при отсутствии указанного ключа
|
# возвращено при отсутствии указанного ключа
|
||||||
filled_dict.get("one", 4) #=> 1
|
filled_dict.get("one", 4) #=> 1
|
||||||
filled_dict.get("four", 4) #=> 4
|
filled_dict.get("four", 4) #=> 4
|
||||||
|
|
||||||
# Метод setdefault - это безопасный способ добавить новую пару ключ-значение в словарь
|
# Метод setdefault вставляет пару ключ-значение, только если такого ключа нет
|
||||||
filled_dict.setdefault("five", 5) #filled_dict["five"] возвращает 5
|
filled_dict.setdefault("five", 5) #filled_dict["five"] возвращает 5
|
||||||
filled_dict.setdefault("five", 6) #filled_dict["five"] по прежнему возвращает 5
|
filled_dict.setdefault("five", 6) #filled_dict["five"] по-прежнему возвращает 5
|
||||||
|
|
||||||
|
|
||||||
# Множества содержат... ну, в общем, множества
|
# Множества содержат... ну, в общем, множества
|
||||||
@@ -237,8 +263,8 @@ empty_set = set()
|
|||||||
# Инициализация множества набором значений
|
# Инициализация множества набором значений
|
||||||
some_set = set([1,2,2,3,4]) # some_set теперь равно set([1, 2, 3, 4])
|
some_set = set([1,2,2,3,4]) # some_set теперь равно set([1, 2, 3, 4])
|
||||||
|
|
||||||
# Начиная с Python 2.7, вы можете использовать {} чтобы обьявить множество
|
# Начиная с Python 2.7, вы можете использовать {}, чтобы объявить множество
|
||||||
filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4}
|
filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4}
|
||||||
|
|
||||||
# Добавление новых элементов в множество
|
# Добавление новых элементов в множество
|
||||||
filled_set.add(5) # filled_set равно {1, 2, 3, 4, 5}
|
filled_set.add(5) # filled_set равно {1, 2, 3, 4, 5}
|
||||||
@@ -262,33 +288,33 @@ filled_set | other_set #=> {1, 2, 3, 4, 5, 6}
|
|||||||
## 3. Поток управления
|
## 3. Поток управления
|
||||||
####################################################
|
####################################################
|
||||||
|
|
||||||
# Для начала заведем переменную
|
# Для начала заведём переменную
|
||||||
some_var = 5
|
some_var = 5
|
||||||
|
|
||||||
# Так выглядит выражение if. Отступы в python очень важны!
|
# Так выглядит выражение if. Отступы в python очень важны!
|
||||||
# результат: "some_var меньше, чем 10"
|
# результат: «some_var меньше, чем 10»
|
||||||
if some_var > 10:
|
if some_var > 10:
|
||||||
print "some_var намного больше, чем 10."
|
print("some_var намного больше, чем 10.")
|
||||||
elif some_var < 10: # Выражение elif необязательно.
|
elif some_var < 10: # Выражение elif необязательно.
|
||||||
print "some_var меньше, чем 10."
|
print("some_var меньше, чем 10.")
|
||||||
else: # Это тоже необязательно.
|
else: # Это тоже необязательно.
|
||||||
print "some_var равно 10."
|
print("some_var равно 10.")
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Циклы For проходят по спискам
|
Циклы For проходят по спискам
|
||||||
|
|
||||||
Результат:
|
Результат:
|
||||||
собака это млекопитающее
|
собака — это млекопитающее
|
||||||
кошка это млекопитающее
|
кошка — это млекопитающее
|
||||||
мышь это млекопитающее
|
мышь — это млекопитающее
|
||||||
"""
|
"""
|
||||||
for animal in ["собака", "кошка", "мышь"]:
|
for animal in ["собака", "кошка", "мышь"]:
|
||||||
# Можете использовать оператор % для интерполяции форматированных строк
|
# Можете использовать оператор % для интерполяции форматированных строк
|
||||||
print "%s это млекопитающее" % animal
|
print("%s — это млекопитающее" % animal)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
`range(number)` возвращает список чисел
|
«range(число)» возвращает список чисел
|
||||||
от нуля до заданного числа
|
от нуля до заданного числа
|
||||||
Результат:
|
Результат:
|
||||||
0
|
0
|
||||||
@@ -297,7 +323,7 @@ for animal in ["собака", "кошка", "мышь"]:
|
|||||||
3
|
3
|
||||||
"""
|
"""
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
print i
|
print(i)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Циклы while продолжаются до тех пор, пока указанное условие не станет ложным.
|
Циклы while продолжаются до тех пор, пока указанное условие не станет ложным.
|
||||||
@@ -309,19 +335,24 @@ for i in range(4):
|
|||||||
"""
|
"""
|
||||||
x = 0
|
x = 0
|
||||||
while x < 4:
|
while x < 4:
|
||||||
print x
|
print(x)
|
||||||
x += 1 # То же самое, что x = x + 1
|
x += 1 # Краткая запись для x = x + 1
|
||||||
|
|
||||||
# Обрабывайте исключения блоками try/except
|
# Обрабатывайте исключения блоками try/except
|
||||||
|
|
||||||
# Работает в Python 2.6 и выше:
|
# Работает в Python 2.6 и выше:
|
||||||
try:
|
try:
|
||||||
# Для выбора ошибки используется raise
|
# Чтобы выбросить ошибку, используется raise
|
||||||
raise IndexError("Это IndexError")
|
raise IndexError("Это ошибка индекса")
|
||||||
except IndexError as e:
|
except IndexError as e:
|
||||||
# pass это просто отсутствие оператора. Обычно здесь происходит
|
# pass это просто отсутствие оператора. Обычно здесь происходит
|
||||||
# восстановление от ошибки.
|
# восстановление после ошибки.
|
||||||
pass
|
pass
|
||||||
|
except (TypeError, NameError):
|
||||||
|
pass # Несколько исключений можно обработать вместе, если нужно.
|
||||||
|
else: # Необязательное выражение. Должно следовать за последним блоком except
|
||||||
|
print("Всё хорошо!") # Выполнится, только если не было никаких исключений
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################################################
|
####################################################
|
||||||
@@ -330,23 +361,23 @@ except IndexError as e:
|
|||||||
|
|
||||||
# Используйте def для создания новых функций
|
# Используйте def для создания новых функций
|
||||||
def add(x, y):
|
def add(x, y):
|
||||||
print "x равен %s, а y равен %s" % (x, y)
|
print("x равен %s, а y равен %s" % (x, y))
|
||||||
return x + y # Возвращайте результат выражением return
|
return x + y # Возвращайте результат выражением return
|
||||||
|
|
||||||
# Вызов функции с аргументами
|
# Вызов функции с аргументами
|
||||||
add(5, 6) #=> prints out "x равен 5, а y равен 6" и возвращает 11
|
add(5, 6) #=> выводит «x равен 5, а y равен 6» и возвращает 11
|
||||||
|
|
||||||
# Другой способ вызова функции с аргументами
|
# Другой способ вызова функции — вызов с именованными аргументами
|
||||||
add(y=6, x=5) # Именованные аргументы можно указывать в любом порядке.
|
add(y=6, x=5) # Именованные аргументы можно указывать в любом порядке.
|
||||||
|
|
||||||
# Вы можете определить функцию, принимающую неизвестное количество аргументов
|
# Вы можете определить функцию, принимающую изменяемое число аргументов
|
||||||
def varargs(*args):
|
def varargs(*args):
|
||||||
return args
|
return args
|
||||||
|
|
||||||
varargs(1, 2, 3) #=> (1,2,3)
|
varargs(1, 2, 3) #=> (1,2,3)
|
||||||
|
|
||||||
|
|
||||||
# А также можете определить функцию, принимающую изменяющееся количество
|
# А также можете определить функцию, принимающую изменяемое число
|
||||||
# именованных аргументов
|
# именованных аргументов
|
||||||
def keyword_args(**kwargs):
|
def keyword_args(**kwargs):
|
||||||
return kwargs
|
return kwargs
|
||||||
@@ -356,8 +387,8 @@ keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"}
|
|||||||
|
|
||||||
# Если хотите, можете использовать оба способа одновременно
|
# Если хотите, можете использовать оба способа одновременно
|
||||||
def all_the_args(*args, **kwargs):
|
def all_the_args(*args, **kwargs):
|
||||||
print args
|
print(args)
|
||||||
print kwargs
|
print(kwargs)
|
||||||
"""
|
"""
|
||||||
all_the_args(1, 2, a=3, b=4) выводит:
|
all_the_args(1, 2, a=3, b=4) выводит:
|
||||||
(1, 2)
|
(1, 2)
|
||||||
@@ -368,11 +399,28 @@ all_the_args(1, 2, a=3, b=4) выводит:
|
|||||||
# Используйте символ * для передачи кортежей и ** для передачи словарей
|
# Используйте символ * для передачи кортежей и ** для передачи словарей
|
||||||
args = (1, 2, 3, 4)
|
args = (1, 2, 3, 4)
|
||||||
kwargs = {"a": 3, "b": 4}
|
kwargs = {"a": 3, "b": 4}
|
||||||
all_the_args(*args) # эквивалент foo(1, 2, 3, 4)
|
all_the_args(*args) # эквивалентно foo(1, 2, 3, 4)
|
||||||
all_the_args(**kwargs) # эквивалент foo(a=3, b=4)
|
all_the_args(**kwargs) # эквивалентно foo(a=3, b=4)
|
||||||
all_the_args(*args, **kwargs) # эквивалент foo(1, 2, 3, 4, a=3, b=4)
|
all_the_args(*args, **kwargs) # эквивалентно foo(1, 2, 3, 4, a=3, b=4)
|
||||||
|
|
||||||
# Python имеет функции первого класса
|
# Область определения функций
|
||||||
|
x = 5
|
||||||
|
|
||||||
|
def setX(num):
|
||||||
|
# Локальная переменная x — это не то же самое, что глобальная переменная x
|
||||||
|
x = num # => 43
|
||||||
|
print (x) # => 43
|
||||||
|
|
||||||
|
def setGlobalX(num):
|
||||||
|
global x
|
||||||
|
print (x) # => 5
|
||||||
|
x = num # Глобальная переменная x теперь равна 6
|
||||||
|
print (x) # => 6
|
||||||
|
|
||||||
|
setX(43)
|
||||||
|
setGlobalX(6)
|
||||||
|
|
||||||
|
# В Python есть функции первого класса
|
||||||
def create_adder(x):
|
def create_adder(x):
|
||||||
def adder(y):
|
def adder(y):
|
||||||
return x + y
|
return x + y
|
||||||
@@ -388,7 +436,7 @@ add_10(3) #=> 13
|
|||||||
map(add_10, [1,2,3]) #=> [11, 12, 13]
|
map(add_10, [1,2,3]) #=> [11, 12, 13]
|
||||||
filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7]
|
filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7]
|
||||||
|
|
||||||
# Мы можем использовать списки для удобного отображения и фильтрации
|
# Для удобного отображения и фильтрации можно использовать списочные включения
|
||||||
[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13]
|
[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13]
|
||||||
[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7]
|
[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7]
|
||||||
|
|
||||||
@@ -402,7 +450,11 @@ class Human(object):
|
|||||||
# Атрибут класса. Он разделяется всеми экземплярами этого класса
|
# Атрибут класса. Он разделяется всеми экземплярами этого класса
|
||||||
species = "H. sapiens"
|
species = "H. sapiens"
|
||||||
|
|
||||||
# Обычный конструктор
|
# Обычный конструктор, вызывается при инициализации экземпляра класса
|
||||||
|
# Обратите внимание, что двойное подчёркивание в начале и в конце имени
|
||||||
|
# означает объекты и атрибуты, которые используются Python, но находятся
|
||||||
|
# в пространствах имён, управляемых пользователем.
|
||||||
|
# Не придумывайте им имена самостоятельно.
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
# Присваивание значения аргумента атрибуту класса name
|
# Присваивание значения аргумента атрибуту класса name
|
||||||
self.name = name
|
self.name = name
|
||||||
@@ -423,17 +475,17 @@ class Human(object):
|
|||||||
return "*grunt*"
|
return "*grunt*"
|
||||||
|
|
||||||
|
|
||||||
# Инстанцирование класса
|
# Инициализация экземпляра класса
|
||||||
i = Human(name="Иван")
|
i = Human(name="Иван")
|
||||||
print i.say("привет") # "Иван: привет"
|
print(i.say("привет")) # Выводит: «Иван: привет»
|
||||||
|
|
||||||
j = Human("Петр")
|
j = Human("Пётр")
|
||||||
print j.say("Привет") # "Петр: привет"
|
print(j.say("Привет")) # Выводит: «Пётр: привет»
|
||||||
|
|
||||||
# Вызов метода класса
|
# Вызов метода класса
|
||||||
i.get_species() #=> "H. sapiens"
|
i.get_species() #=> "H. sapiens"
|
||||||
|
|
||||||
# Присвоение разделяемому атрибуту
|
# Изменение разделяемого атрибута
|
||||||
Human.species = "H. neanderthalensis"
|
Human.species = "H. neanderthalensis"
|
||||||
i.get_species() #=> "H. neanderthalensis"
|
i.get_species() #=> "H. neanderthalensis"
|
||||||
j.get_species() #=> "H. neanderthalensis"
|
j.get_species() #=> "H. neanderthalensis"
|
||||||
@@ -448,12 +500,12 @@ Human.grunt() #=> "*grunt*"
|
|||||||
|
|
||||||
# Вы можете импортировать модули
|
# Вы можете импортировать модули
|
||||||
import math
|
import math
|
||||||
print math.sqrt(16) #=> 4
|
print(math.sqrt(16)) #=> 4
|
||||||
|
|
||||||
# Вы можете импортировать отдельные функции модуля
|
# Вы можете импортировать отдельные функции модуля
|
||||||
from math import ceil, floor
|
from math import ceil, floor
|
||||||
print ceil(3.7) #=> 4.0
|
print(ceil(3.7)) #=> 4.0
|
||||||
print floor(3.7) #=> 3.0
|
print(floor(3.7)) #=> 3.0
|
||||||
|
|
||||||
# Можете импортировать все функции модуля.
|
# Можете импортировать все функции модуля.
|
||||||
# (Хотя это и не рекомендуется)
|
# (Хотя это и не рекомендуется)
|
||||||
@@ -463,7 +515,7 @@ from math import *
|
|||||||
import math as m
|
import math as m
|
||||||
math.sqrt(16) == m.sqrt(16) #=> True
|
math.sqrt(16) == m.sqrt(16) #=> True
|
||||||
|
|
||||||
# Модули в Python это обычные файлы с кодом python. Вы
|
# Модули в Python — это обычные Python-файлы. Вы
|
||||||
# можете писать свои модули и импортировать их. Название
|
# можете писать свои модули и импортировать их. Название
|
||||||
# модуля совпадает с названием файла.
|
# модуля совпадает с названием файла.
|
||||||
|
|
||||||
@@ -472,18 +524,72 @@ math.sqrt(16) == m.sqrt(16) #=> True
|
|||||||
import math
|
import math
|
||||||
dir(math)
|
dir(math)
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
## 7. Дополнительно
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
# Генераторы помогут выполнить ленивые вычисления
|
||||||
|
def double_numbers(iterable):
|
||||||
|
for i in iterable:
|
||||||
|
yield i + i
|
||||||
|
|
||||||
|
# Генератор создаёт значения на лету.
|
||||||
|
# Он не возвращает все значения разом, а создаёт каждое из них при каждой
|
||||||
|
# итерации. Это значит, что значения больше 15 в double_numbers
|
||||||
|
# обработаны не будут.
|
||||||
|
# Обратите внимание: xrange — это генератор, который делает то же, что и range.
|
||||||
|
# Создание списка чисел от 1 до 900000000 требует много места и времени.
|
||||||
|
# xrange создаёт объект генератора, а не список сразу, как это делает range.
|
||||||
|
# Если нам нужно имя переменной, совпадающее с ключевым словом Python,
|
||||||
|
# мы используем подчёркивание в конце
|
||||||
|
xrange_ = xrange(1, 900000000)
|
||||||
|
|
||||||
|
# Будет удваивать все числа, пока результат не будет >= 30
|
||||||
|
for i in double_numbers(xrange_):
|
||||||
|
print(i)
|
||||||
|
if i >= 30:
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
# Декораторы
|
||||||
|
# В этом примере beg оборачивает say
|
||||||
|
# Метод beg вызовет say. Если say_please равно True,
|
||||||
|
# он изменит возвращаемое сообщение
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
|
|
||||||
|
def beg(target_function):
|
||||||
|
@wraps(target_function)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
msg, say_please = target_function(*args, **kwargs)
|
||||||
|
if say_please:
|
||||||
|
return "{} {}".format(msg, " Пожалуйста! У меня нет денег :(")
|
||||||
|
return msg
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@beg
|
||||||
|
def say(say_please=False):
|
||||||
|
msg = "Вы не купите мне пива?"
|
||||||
|
return msg, say_please
|
||||||
|
|
||||||
|
|
||||||
|
print(say()) # Вы не купите мне пива?
|
||||||
|
print(say(say_please=True)) # Вы не купите мне пива? Пожалуйста! У меня нет денег :(
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Хотите еще?
|
## Хотите ещё?
|
||||||
|
|
||||||
### Бесплатные онлайн-материалы
|
### Бесплатные онлайн-материалы
|
||||||
|
|
||||||
* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
|
* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
|
||||||
* [Dive Into Python](http://www.diveintopython.net/)
|
* [Dive Into Python](http://www.diveintopython.net/)
|
||||||
* [The Official Docs](http://docs.python.org/2.6/)
|
* [Официальная документация](http://docs.python.org/2.6/)
|
||||||
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
|
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
|
||||||
* [Python Module of the Week](http://pymotw.com/2/)
|
* [Python Module of the Week](http://pymotw.com/2/)
|
||||||
|
* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
|
||||||
|
|
||||||
### Платные
|
### Платные
|
||||||
|
|
||||||
|
244
tmux.html.markdown
Normal file
244
tmux.html.markdown
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
---
|
||||||
|
category: tool
|
||||||
|
tool: tmux
|
||||||
|
contributors:
|
||||||
|
- ["kaernyk", "http://github.com/kaernyk"]
|
||||||
|
filename: LearnTmux.txt
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
<a href="http://tmux.sourceforge.net/">
|
||||||
|
tmux</a> is a terminal multiplexer: it enables a number of terminals
|
||||||
|
to be created, accessed, and controlled from a single screen. tmux
|
||||||
|
may be detached from a screen and continue running in the background
|
||||||
|
then later reattached.
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
tmux [command] # Run a command
|
||||||
|
# 'tmux' with no commands will create a new
|
||||||
|
session
|
||||||
|
|
||||||
|
new # Create a new session
|
||||||
|
-s "Session" # Create named session
|
||||||
|
-n "Window" # Create named Window
|
||||||
|
-c "/dir" # Start in target directory
|
||||||
|
|
||||||
|
attach # Attach last/available session
|
||||||
|
-t "#" # Attach target session
|
||||||
|
-d # Detach the session from other instances
|
||||||
|
|
||||||
|
ls # List open sessions
|
||||||
|
-a # List all open sessions
|
||||||
|
|
||||||
|
lsw # List windows
|
||||||
|
-a # List all windows
|
||||||
|
-s # List all windows in session
|
||||||
|
|
||||||
|
lsp # List panes
|
||||||
|
-a # List all panes
|
||||||
|
-s # List all panes in session
|
||||||
|
-t # List app panes in target
|
||||||
|
|
||||||
|
kill-window # Kill current window
|
||||||
|
-t "#" # Kill target window
|
||||||
|
-a # Kill all windows
|
||||||
|
-a -t "#" # Kill all windows but the target
|
||||||
|
|
||||||
|
kill-session # Kill current session
|
||||||
|
-t "#" # Kill target session
|
||||||
|
-a # Kill all sessions
|
||||||
|
-a -t "#" # Kill all sessions but the target
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Key Bindings
|
||||||
|
|
||||||
|
# The method of controlling an attached tmux session is via key
|
||||||
|
# combinations called 'Prefix' keys.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
(C-b) = Ctrl + b # 'Prefix' combination required to use keybinds
|
||||||
|
|
||||||
|
(M-1) = Meta + 1 -or- Alt + 1
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
? # List all key bindings
|
||||||
|
: # Enter the tmux command prompt
|
||||||
|
r # Force redraw of the attached client
|
||||||
|
c # Create a new window
|
||||||
|
|
||||||
|
! # Break the current pane out of the window.
|
||||||
|
% # Split the current pane into two, left and right
|
||||||
|
" # Split the current pane into two, top and bottom
|
||||||
|
|
||||||
|
n # Change to the next window
|
||||||
|
p # Change to the previous window
|
||||||
|
{ # Swap the current pane with the previous pane
|
||||||
|
} # Swap the current pane with the next pane
|
||||||
|
|
||||||
|
s # Select a new session for the attached client
|
||||||
|
interactively
|
||||||
|
w # Choose the current window interactively
|
||||||
|
0 to 9 # Select windows 0 to 9
|
||||||
|
|
||||||
|
d # Detach the current client
|
||||||
|
D # Choose a client to detach
|
||||||
|
|
||||||
|
& # Kill the current window
|
||||||
|
x # Kill the current pane
|
||||||
|
|
||||||
|
Up, Down # Change to the pane above, below, left, or right
|
||||||
|
Left, Right
|
||||||
|
|
||||||
|
M-1 to M-5 # Arrange panes:
|
||||||
|
# 1) even-horizontal
|
||||||
|
# 2) even-vertical
|
||||||
|
# 3) main-horizontal
|
||||||
|
# 4) main-vertical
|
||||||
|
# 5) tiled
|
||||||
|
|
||||||
|
C-Up, C-Down # Resize the current pane in steps of one cell
|
||||||
|
C-Left, C-Right
|
||||||
|
|
||||||
|
M-Up, M-Down # Resize the current pane in steps of five cells
|
||||||
|
M-Left, M-Right
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Configuring ~/.tmux.conf
|
||||||
|
|
||||||
|
tmux.conf can be used to set options automatically on start up, much
|
||||||
|
like how .vimrc or init.el are used.
|
||||||
|
|
||||||
|
# Example tmux.conf
|
||||||
|
# 2014.9
|
||||||
|
|
||||||
|
|
||||||
|
### Keybinds
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
# Unbind C-b as the default prefix
|
||||||
|
unbind-key C-befix C-a
|
||||||
|
|
||||||
|
# Return to previous window when prefix is pressed twice
|
||||||
|
bind-key C-a last-window
|
||||||
|
bind-key ` last-window
|
||||||
|
|
||||||
|
# Allow swapping C-a and ` using F11/F12
|
||||||
|
bind-key F11 set-option -g prefix C-a
|
||||||
|
bind-key F12 set-option -g prefix `
|
||||||
|
|
||||||
|
# Activate inner-most session (when nesting tmux)
|
||||||
|
# to send commands
|
||||||
|
bind-key a send-prefix
|
||||||
|
|
||||||
|
# Index Start
|
||||||
|
set -g base-index 1
|
||||||
|
|
||||||
|
# Window Cycle/Swap
|
||||||
|
bind e previous-window
|
||||||
|
bind f next-window
|
||||||
|
bind E swap-window -t -1
|
||||||
|
bind F swap-window -t +1
|
||||||
|
|
||||||
|
# easy-to-remember split pane commands
|
||||||
|
bind | split-window -h
|
||||||
|
bind - split-window -v
|
||||||
|
unbind '"'
|
||||||
|
unbind %
|
||||||
|
|
||||||
|
# moving between panes with vim movement keys
|
||||||
|
bind h select-pane -L
|
||||||
|
bind j select-pane -D
|
||||||
|
bind k select-pane -U
|
||||||
|
bind l select-pane -R
|
||||||
|
|
||||||
|
|
||||||
|
### Theme
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
# Statusbar Color Palette
|
||||||
|
set-option -g status-justify left
|
||||||
|
set-option -g status-bg black
|
||||||
|
set-option -g status-fg white
|
||||||
|
set-option -g status-left-length 40
|
||||||
|
set-option -g status-right-length 80
|
||||||
|
|
||||||
|
# Pane Border Color Palette
|
||||||
|
set-option -g pane-active-border-fg green
|
||||||
|
set-option -g pane-active-border-bg black
|
||||||
|
set-option -g pane-border-fg white
|
||||||
|
set-option -g pane-border-bg black
|
||||||
|
|
||||||
|
# Message Color Palette
|
||||||
|
set-option -g message-fg black
|
||||||
|
set-option -g message-bg green
|
||||||
|
|
||||||
|
# Window Status Color Palette
|
||||||
|
setw -g window-status-bg black
|
||||||
|
setw -g window-status-current-fg green
|
||||||
|
setw -g window-status-bell-attr default
|
||||||
|
setw -g window-status-bell-fg red
|
||||||
|
setw -g window-status-content-attr default
|
||||||
|
setw -g window-status-content-fg yellow
|
||||||
|
setw -g window-status-activity-attr default
|
||||||
|
setw -g window-status-activity-fg yellow
|
||||||
|
|
||||||
|
|
||||||
|
### UI
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
# Statusbar
|
||||||
|
set-option -g status-utf8 on
|
||||||
|
|
||||||
|
# Keybind preference
|
||||||
|
setw -g mode-keys vi
|
||||||
|
set-option -g status-keys vi
|
||||||
|
|
||||||
|
# Notification
|
||||||
|
setw -g monitor-activity on
|
||||||
|
set -g visual-activity on
|
||||||
|
set-option -g bell-action any
|
||||||
|
set-option -g visual-bell off
|
||||||
|
|
||||||
|
# Mouse
|
||||||
|
setw -g mode-mouse on
|
||||||
|
set-option -g mouse-select-pane on
|
||||||
|
set -g mouse-resize-pane on
|
||||||
|
set -g mouse-select-window on
|
||||||
|
|
||||||
|
# Automatically set window titles
|
||||||
|
set-option -g set-titles on
|
||||||
|
|
||||||
|
# window number,program name,active (or not)
|
||||||
|
set-option -g set-titles-string '#H:#S.#I.#P #W #T'
|
||||||
|
|
||||||
|
# Statusbar Adjustments
|
||||||
|
set -g status-left '#[fg=red]#H#[fg=green]:#[fg=white]#S #[fg=green]][#[default]'
|
||||||
|
set -g status-interval 3
|
||||||
|
|
||||||
|
# Statusbar with right-aligned Date / Time
|
||||||
|
#set -g status-right '#[fg=green]][#[fg=white] #T #[fg=green]][ #[fg=blue]%Y-%m-%d #[fg=white]%H:%M#[default]'
|
||||||
|
|
||||||
|
# Show performance counters in statusbar
|
||||||
|
# Requires https://github.com/thewtex/tmux-mem-cpu-load/
|
||||||
|
#set -g status-right '#[fg=green]][#[fg=white] #(tmux-mem-cpu-load 5 4) #[fg=green]][ #[fg=yellow]%H:%M#[default]'
|
||||||
|
|
||||||
|
|
||||||
|
### Misc
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
# Scrollback/History limit
|
||||||
|
set -g history-limit 4096
|
||||||
|
|
||||||
|
bind r source-file ~/.tmux.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### External Resources
|
||||||
|
|
||||||
|
<a href="http://tmux.sourceforge.net/">Tmux | Home</a><br>
|
||||||
|
<a href="http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man1/tmux.1?query=tmux">Tmux Manual page</a><br>
|
||||||
|
<a href="http://wiki.gentoo.org/wiki/Tmux">Archlinux Wiki</a><br>
|
||||||
|
<a href="https://wiki.archlinux.org/index.php/Tmux">Gentoo Wiki</a><br>
|
||||||
|
<a href="https://stackoverflow.com/questions/11558907/is-there-a-better-way-to-display-cpu-usage-in-tmux">Display CPU/MEM % in statusbar</a><br>
|
@@ -9,6 +9,7 @@ contributors:
|
|||||||
- ["Amr Tamimi", "https://amrtamimi.com"]
|
- ["Amr Tamimi", "https://amrtamimi.com"]
|
||||||
translators:
|
translators:
|
||||||
- ["Jakukyo Friel", "http://weakish.github.io"]
|
- ["Jakukyo Friel", "http://weakish.github.io"]
|
||||||
|
filename: lua-cn.lua
|
||||||
---
|
---
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
|
@@ -3,7 +3,7 @@ language: Markdown
|
|||||||
contributors:
|
contributors:
|
||||||
- ["Dan Turkel", "http://danturkel.com/"]
|
- ["Dan Turkel", "http://danturkel.com/"]
|
||||||
translators:
|
translators:
|
||||||
- ["Fangzhou Chen"]
|
- ["Fangzhou Chen","https://github.com/FZSS"]
|
||||||
filename: learnmarkdown-cn.md
|
filename: learnmarkdown-cn.md
|
||||||
lang: zh-cn
|
lang: zh-cn
|
||||||
---
|
---
|
||||||
|
Reference in New Issue
Block a user