Repository: Y-Dian/LearnXinYminutes
Branch: master
Commit: 51541abd7ecc
Files: 14
Total size: 102.3 KB
Directory structure:
gitextract_caczyvz4/
├── README.md
├── learnbash-cn.sh
├── learnc-cn.c
├── learncsharp-cn.cs
├── learncss-cn.css
├── learngo-cn.go
├── learnlua-cn.lua
├── learnperl-cn.pl
├── learnphp-cn.php
├── learnpython-cn.py
├── learnpython3-cn.py
├── learnr-cn.r
├── learnruby-cn.rb
└── learnswift-cn.swift
================================================
FILE CONTENTS
================================================
================================================
FILE: README.md
================================================
# Learn X in Y minutes
在线编程语言速学网,C++、CSS、java、json、PHP、python、swift等各种语言的快速学习教程。
- [C](https://github.com/Y-Dian/LearnXinYminutes/blob/master/learnc-cn.c)
- [C#](https://github.com/Y-Dian/LearnXinYminutes/blob/master/learncsharp-cn.cs)
- [Go](https://github.com/Y-Dian/LearnXinYminutes/blob/master/learngo-cn.go)
- [Lua](https://github.com/Y-Dian/LearnXinYminutes/blob/master/learnlua-cn.lua)
- [Perl](https://github.com/Y-Dian/LearnXinYminutes/blob/master/learnperl-cn.pl)
- [PHP](https://github.com/Y-Dian/LearnXinYminutes/blob/master/learnphp-cn.php)
- [Python](https://github.com/Y-Dian/LearnXinYminutes/blob/master/learnpython-cn.py)
- [Python3](https://github.com/Y-Dian/LearnXinYminutes/blob/master/learnpython3-cn.py)
- [R](https://github.com/Y-Dian/LearnXinYminutes/blob/master/learnr-cn.r)
- [Ruby](https://github.com/Y-Dian/LearnXinYminutes/blob/master/learnruby-cn.rb)
- [Swift](https://github.com/Y-Dian/LearnXinYminutes/blob/master/learnswift-cn.swift)
- [CSS](https://github.com/Y-Dian/LearnXinYminutes/blob/master/learncss-cn.css)
- [Bash](https://github.com/Y-Dian/LearnXinYminutes/blob/master/learnbash-cn.sh)
================================================
FILE: learnbash-cn.sh
================================================
#!/bin/bash
# 脚本的第一行叫 shebang,用来告知系统如何执行该脚本:
# 参见: http://en.wikipedia.org/wiki/Shebang_(Unix)
# 如你所见,注释以 # 开头,shebang 也是注释。
# 显示 “Hello world!”
echo Hello, world!
# 每一句指令以换行或分号隔开:
echo 'This is the first line'; echo 'This is the second line'
# 声明一个变量:
VARIABLE="Some string"
# 下面是错误的做法:
VARIABLE = "Some string"
# Bash 会把 VARIABLE 当做一个指令,由于找不到该指令,因此这里会报错。
# 使用变量:
echo $VARIABLE
echo "$VARIABLE"
echo '$VARIABLE'
# 当你赋值 (assign) 、导出 (export),或者以其他方式使用变量时,变量名前不加 $。
# 如果要使用变量的值, 则要加 $。
# 注意: ' (单引号) 不会展开变量(即会屏蔽掉变量)。
# 在变量内部进行字符串代换
echo ${VARIABLE/Some/A}
# 会把 VARIABLE 中首次出现的 "some" 替换成 “A”。
# 内置变量:
# 下面的内置变量很有用
echo "Last program return value: $?"
echo "Script's PID: $$"
echo "Number of arguments: $#"
echo "Scripts arguments: $@"
echo "Scripts arguments separeted in different variables: $1 $2..."
# 读取输入:
echo "What's your name?"
read NAME # 这里不需要声明新变量
echo Hello, $NAME!
# 通常的 if 结构看起来像这样:
# 'man test' 可查看更多的信息
if [ $NAME -ne $USER ]
then
echo "Your name is you username"
else
echo "Your name isn't you username"
fi
# 根据上一个指令执行结果决定是否执行下一个指令
echo "Always executed" || echo "Only executed if first command fail"
echo "Always executed" && echo "Only executed if first command does NOT fail"
# 表达式的格式如下:
echo $(( 10 + 5 ))
# 与其他编程语言不同的是,bash 运行时依赖上下文。比如,使用 ls 时,列出当前目录。
ls
# 指令可以带有选项:
ls -l # 列出文件和目录的详细信息
# 前一个指令的输出可以当作后一个指令的输入。grep 用来匹配字符串。
# 用下面的指令列出当前目录下所有的 txt 文件:
ls -l | grep "\.txt"
# 重定向可以到输出,输入和错误输出。
python2 hello.py < "input.in"
python2 hello.py > "output.out"
python2 hello.py 2> "error.err"
# > 会覆盖已存在的文件, >> 会以累加的方式输出文件中。
# 一个指令可用 $( ) 嵌套在另一个指令内部:
# 以下的指令会打印当前目录下的目录和文件总数
echo "There are $(ls | wc -l) items here."
# Bash 的 case 语句与 Java 和 C++ 中的 switch 语句类似:
case "$VARIABLE" in
# 列出需要匹配的字符串
0) echo "There is a zero.";;
1) echo "There is a one.";;
*) echo "It is not null.";;
esac
# 循环遍历给定的参数序列:
# 变量$VARIABLE 的值会被打印 3 次。
# 注意 ` ` 和 $( ) 等价。seq 返回长度为 3 的数组。
for VARIABLE in `seq 3`
do
echo "$VARIABLE"
done
# 你也可以使用函数
# 定义函数:
function foo ()
{
echo "Arguments work just like script arguments: $@"
echo "And: $1 $2..."
echo "This is a function"
return 0
}
# 更简单的方法
bar ()
{
echo "Another way to declare functions!"
return 0
}
# 调用函数
foo "My name is" $NAME
# 有很多有用的指令需要学习:
tail -n 10 file.txt
# 打印 file.txt 的最后 10 行
head -n 10 file.txt
# 打印 file.txt 的前 10 行
sort file.txt
# 将 file.txt 按行排序
uniq -d file.txt
# 报告或忽略重复的行,用选项 -d 打印重复的行
cut -d ',' -f 1 file.txt
# 打印每行中 ',' 之前内容
================================================
FILE: learnc-cn.c
================================================
// 单行注释以//开始。(仅适用于C99或更新的版本。)
/*
多行注释是这个样子的。(C89也适用。)
*/
// 常数: #define 关键词
#define DAYS_IN_YEAR 365
// 以枚举的方式定义常数
enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT};
// MON自动被定义为2,TUE被定义为3,以此类推。
// 用#include来导入头文件
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// <尖括号>间的文件名是C标准库的头文件。
// 标准库以外的头文件,使用双引号代替尖括号。
#include "my_header.h"
// 函数的签名可以事先在.h文件中定义,
// 也可以直接在.c文件的头部定义。
void function_1(char c);
void function_2(void);
// 如果函数出现在main()之后,那么必须在main()之前
// 先声明一个函数原型
int add_two_ints(int x1, int x2); // 函数原型
// 你的程序的入口是一个返回值为整型的main函数
int main() {
// 用printf打印到标准输出,可以设定格式,
// %d 代表整数, \n 代表换行
printf("%d\n", 0); // => 打印 0
// 所有的语句都要以分号结束
///////////////////////////////////////
// 类型
///////////////////////////////////////
// 在使用变量之前我们必须先声明它们。
// 变量在声明时需要指明其类型,而类型能够告诉系统这个变量所占用的空间
// int型(整型)变量一般占用4个字节
int x_int = 0;
// short型(短整型)变量一般占用2个字节
short x_short = 0;
// char型(字符型)变量会占用1个字节
char x_char = 0;
char y_char = 'y'; // 字符变量的字面值需要用单引号包住
// long型(长整型)一般需要4个字节到8个字节; 而long long型则至少需要8个字节(64位)
long x_long = 0;
long long x_long_long = 0;
// float一般是用32位表示的浮点数字
float x_float = 0.0;
// double一般是用64位表示的浮点数字
double x_double = 0.0;
// 整数类型也可以有无符号的类型表示。这样这些变量就无法表示负数
// 但是无符号整数所能表示的范围就可以比原来的整数大一些
unsigned short ux_short;
unsigned int ux_int;
unsigned long long ux_long_long;
// 单引号内的字符是机器的字符集中的整数。
'0' // => 在ASCII字符集中是48
'A' // => 在ASCII字符集中是65
// char类型一定会占用1个字节,但是其他的类型却会因具体机器的不同而各异
// sizeof(T) 可以返回T类型在运行的机器上占用多少个字节
// 这样你的代码就可以在各处正确运行了
// sizeof(obj)返回表达式(变量、字面量等)的尺寸
printf("%zu\n", sizeof(int)); // => 4 (大多数的机器字长为4)
// 如果`sizeof`的参数是一个表达式,那么这个参数不会被演算(VLA例外,见下)
// 它产生的值是编译期的常数
int a = 1;
// size_t是一个无符号整型,表示对象的尺寸,至少2个字节
size_t size = sizeof(a++); // a++ 不会被演算
printf("sizeof(a++) = %zu where a = %d\n", size, a);
// 打印 "sizeof(a++) = 4 where a = 1" (在32位架构上)
// 数组必须要被初始化为具体的长度
char my_char_array[20]; // 这个数组占据 1 * 20 = 20 个字节
int my_int_array[20]; // 这个数组占据 4 * 20 = 80 个字节
// (这里我们假设字长为4)
// 可以用下面的方法把数组初始化为0:
char my_array[20] = {0};
// 索引数组和其他语言类似 -- 好吧,其实是其他的语言像C
my_array[0]; // => 0
// 数组是可变的,其实就是内存的映射!
my_array[1] = 2;
printf("%d\n", my_array[1]); // => 2
// 在C99 (C11中是可选特性),变长数组(VLA)也可以声明长度。
// 其长度不用是编译期常量。
printf("Enter the array size: "); // 询问用户数组长度
char buf[0x100];
fgets(buf, sizeof buf, stdin);
// stroul 将字符串解析为无符号整数
size_t size = strtoul(buf, NULL, 10);
int var_length_array[size]; // 声明VLA
printf("sizeof array = %zu\n", sizeof var_length_array);
// 上述程序可能的输出为:
// > Enter the array size: 10
// > sizeof array = 40
// 字符串就是以 NUL (0x00) 这个字符结尾的字符数组,
// NUL可以用'\0'来表示.
// (在字符串字面量中我们不必输入这个字符,编译器会自动添加的)
char a_string[20] = "This is a string";
printf("%s\n", a_string); // %s 可以对字符串进行格式化
/*
也许你会注意到 a_string 实际上只有16个字节长.
第17个字节是一个空字符(NUL)
而第18, 19 和 20 个字符的值是未定义。
*/
printf("%d\n", a_string[16]); // => 0
// byte #17值为0(18,19,20同样为0)
// 单引号间的字符是字符字面量
// 它的类型是`int`,而 *不是* `char`
// (由于历史原因)
int cha = 'a'; // 合法
char chb = 'a'; // 同样合法 (隐式类型转换
// 多维数组
int multi_array[2][5] = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 0}
}
// 获取元素
int array_int = multi_array[0][2]; // => 3
///////////////////////////////////////
// 操作符
///////////////////////////////////////
// 多个变量声明的简写
int i1 = 1, i2 = 2;
float f1 = 1.0, f2 = 2.0;
int a, b, c;
a = b = c = 0;
// 算数运算直截了当
i1 + i2; // => 3
i2 - i1; // => 1
i2 * i1; // => 2
i1 / i2; // => 0 (0.5,但会被化整为 0)
f1 / f2; // => 0.5, 也许会有很小的误差
// 浮点数和浮点数运算都是近似值
// 取余运算
11 % 3; // => 2
// 你多半会觉得比较操作符很熟悉, 不过C中没有布尔类型
// 而是用整形替代
// (C99中有_Bool或bool。)
// 0为假, 其他均为真. (比较操作符的返回值总是返回0或1)
3 == 2; // => 0 (false)
3 != 2; // => 1 (true)
3 > 2; // => 1
3 < 2; // => 0
2 <= 2; // => 1
2 >= 2; // => 1
// C不是Python —— 连续比较不合法
int a = 1;
// 错误
int between_0_and_2 = 0 < a < 2;
// 正确
int between_0_and_2 = 0 < a && a < 2;
// 逻辑运算符适用于整数
!3; // => 0 (非)
!0; // => 1
1 && 1; // => 1 (且)
0 && 1; // => 0
0 || 1; // => 1 (或)
0 || 0; // => 0
// 条件表达式 ( ? : )
int a = 5;
int b = 10;
int z;
z = (a > b) ? a : b; // 10 “若a > b返回a,否则返回b。”
// 增、减
char *s = "iLoveC"
int j = 0;
s[j++]; // "i" 返回s的第j项,然后增加j的值。
j = 0;
s[++j]; // => "L" 增加j的值,然后返回s的第j项。
// j-- 和 --j 同理
// 位运算
~0x0F; // => 0xF0 (取反)
0x0F & 0xF0; // => 0x00 (和)
0x0F | 0xF0; // => 0xFF (或)
0x04 ^ 0x0F; // => 0x0B (异或)
0x01 << 1; // => 0x02 (左移1位)
0x02 >> 1; // => 0x01 (右移1位)
// 对有符号整数进行移位操作要小心 —— 以下未定义:
// 有符号整数位移至符号位 int a = 1 << 32
// 左移位一个负数 int a = -1 << 2
// 移位超过或等于该类型数值的长度
// int a = 1 << 32; // 假定int32位
///////////////////////////////////////
// 控制结构
///////////////////////////////////////
if (0) {
printf("I am never run\n");
} else if (0) {
printf("I am also never run\n");
} else {
printf("I print\n");
}
// While循环
int ii = 0;
while (ii < 10) { // 任何非0的值均为真
printf("%d, ", ii++); // ii++ 在取值过后自增
} // => 打印 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
printf("\n");
int kk = 0;
do {
printf("%d, ", kk);
} while (++kk < 10); // ++kk 先自增,再被取值
// => 打印 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
printf("\n");
// For 循环
int jj;
for (jj=0; jj < 10; jj++) {
printf("%d, ", jj);
} // => 打印 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
printf("\n");
// *****注意*****:
// 循环和函数必须有主体部分,如果不需要主体部分:
int i;
for (i = 0; i <= 5; i++) {
; // 使用分号表达主体(null语句)
}
// 多重分支:switch()
switch (some_integral_expression) {
case 0: // 标签必须是整数常量表达式
do_stuff();
break; // 如果不使用break,控制结构会继续执行下面的标签
case 1:
do_something_else();
break;
default:
// 假设 `some_integral_expression` 不匹配任何标签
fputs("error!\n", stderr);
exit(-1);
break;
}
///////////////////////////////////////
// 类型转换
///////////////////////////////////////
// 在C中每个变量都有类型,你可以将变量的类型进行转换
// (有一定限制)
int x_hex = 0x01; // 可以用16进制字面量赋值
// 在类型转换时,数字本身的值会被保留下来
printf("%d\n", x_hex); // => 打印 1
printf("%d\n", (short) x_hex); // => 打印 1
printf("%d\n", (char) x_hex); // => 打印 1
// 类型转换时可能会造成溢出,而且不会抛出警告
printf("%d\n", (char) 257); // => 1 (char的最大值为255,假定char为8位长)
// 使用<limits.h>提供的CHAR_MAX、SCHAR_MAX和UCHAR_MAX宏可以确定`char`、`signed_char`和`unisigned char`的最大值。
// 整数型和浮点型可以互相转换
printf("%f\n", (float)100); // %f 格式化单精度浮点
printf("%lf\n", (double)100); // %lf 格式化双精度浮点
printf("%d\n", (char)100.0);
///////////////////////////////////////
// 指针
///////////////////////////////////////
// 指针变量是用来储存内存地址的变量
// 指针变量的声明也会告诉它所指向的数据的类型
// 你可以使用得到你的变量的地址,并把它们搞乱,;-)
int x = 0;
printf("%p\n", &x); // 用 & 来获取变量的地址
// (%p 格式化一个类型为 void *的指针)
// => 打印某个内存地址
// 指针类型在声明中以*开头
int* px, not_a_pointer; // px是一个指向int型的指针
px = &x; // 把x的地址保存到px中
printf("%p\n", (void *)px); // => 输出内存中的某个地址
printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer));
// => 在64位系统上打印“8, 4”。
// 要得到某个指针指向的内容的值,可以在指针前加一个*来取得(取消引用)
// 注意: 是的,这可能让人困惑,'*'在用来声明一个指针的同时取消引用它。
printf("%d\n", *px); // => 输出 0, 即x的值
// 你也可以改变指针所指向的值
// 此时你需要取消引用上添加括号,因为++比*的优先级更高
(*px)++; // 把px所指向的值增加1
printf("%d\n", *px); // => 输出 1
printf("%d\n", x); // => 输出 1
// 数组是分配一系列连续空间的常用方式
int x_array[20];
int xx;
for (xx=0; xx<20; xx++) {
x_array[xx] = 20 - xx;
} // 初始化 x_array 为 20, 19, 18,... 2, 1
// 声明一个整型的指针,并初始化为指向x_array
int* x_ptr = x_array;
// x_ptr现在指向了数组的第一个元素(即整数20).
// 这是因为数组通常衰减为指向它们的第一个元素的指针。
// 例如,当一个数组被传递给一个函数或者绑定到一个指针时,
//它衰减为(隐式转化为)一个指针。
// 例外: 当数组是`&`操作符的参数:
int arr[10];
int (*ptr_to_arr)[10] = &arr; // &arr的类型不是`int *`!
// 它的类型是指向数组的指针(数组由10个int组成)
// 或者当数组是字符串字面量(初始化字符数组)
char arr[] = "foobarbazquirk";
// 或者当它是`sizeof`或`alignof`操作符的参数时:
int arr[10];
int *ptr = arr; // 等价于 int *ptr = &arr[0];
printf("%zu, %zu\n", sizeof arr, sizeof ptr); // 应该会输出"40, 4"或"40, 8"
// 指针的增减多少是依据它本身的类型而定的
// (这被称为指针算术)
printf("%d\n", *(x_ptr + 1)); // => 打印 19
printf("%d\n", x_array[1]); // => 打印 19
// 你也可以通过标准库函数malloc来实现动态分配
// 这个函数接受一个代表容量的参数,参数类型为`size_t`
// 系统一般会从堆区分配指定容量字节大小的空间
// (在一些系统,例如嵌入式系统中这点不一定成立
// C标准对此未置一词。)
int *my_ptr = malloc(sizeof(*my_ptr) * 20);
for (xx=0; xx<20; xx++) {
*(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx
} // 初始化内存为 20, 19, 18, 17... 2, 1 (类型为int)
// 对未分配的内存进行取消引用会产生未定义的结果
printf("%d\n", *(my_ptr + 21)); // => 谁知道会输出什么
// malloc分配的区域需要手动释放
// 否则没人能够再次使用这块内存,直到程序结束为止
free(my_ptr);
// 字符串通常是字符数组,但是经常用字符指针表示
// (它是指向数组的第一个元素的指针)
// 一个优良的实践是使用`const char *`来引用一个字符串字面量,
// 因为字符串字面量不应当被修改(即"foo"[0] = 'a'犯了大忌)
const char* my_str = "This is my very own string";
printf("%c\n", *my_str); // => 'T'
// 如果字符串是数组,(多半是用字符串字面量初始化的)
// 情况就不一样了,字符串位于可写的内存中
char foo[] = "foo";
foo[0] = 'a'; // 这是合法的,foo现在包含"aoo"
function_1();
} // main函数结束
///////////////////////////////////////
// 函数
///////////////////////////////////////
// 函数声明语法:
// <返回值类型> <函数名称>(<参数>)
int add_two_ints(int x1, int x2){
return x1 + x2; // 用return来返回一个值
}
/*
函数是按值传递的。当调用一个函数的时候,传递给函数的参数
是原有值的拷贝(数组除外)。你在函数内对参数所进行的操作
不会改变该参数原有的值。
但是你可以通过指针来传递引用,这样函数就可以更改值
例子:字符串本身翻转
*/
// 类型为void的函数没有返回值
void str_reverse(char *str_in){
char tmp;
int ii = 0;
size_t len = strlen(str_in); // `strlen()`` 是C标准库函数
for(ii = 0; ii < len / 2; ii++){
tmp = str_in[ii];
str_in[ii] = str_in[len - ii - 1]; // 从倒数第ii个开始
str_in[len - ii - 1] = tmp;
}
}
/*
char c[] = "This is a test.";
str_reverse(c);
printf("%s\n", c); // => ".tset a si sihT"
*/
// 如果引用函数之外的变量,必须使用extern关键字
int i = 0;
void testFunc() {
extern int i; // 使用外部变量 i
}
// 使用static确保external变量为源文件私有
static int i = 0; // 其他使用 testFunc()的文件无法访问变量i
void testFunc() {
extern int i;
}
//**你同样可以声明函数为static**
///////////////////////////////////////
// 用户自定义类型和结构
///////////////////////////////////////
// Typedefs可以创建类型别名
typedef int my_type;
my_type my_type_var = 0;
// struct是数据的集合,成员依序分配,按照
// 编写的顺序
struct rectangle {
int width;
int height;
};
// 一般而言,以下断言不成立:
// sizeof(struct rectangle) == sizeof(int) + sizeof(int)
//这是因为structure成员之间可能存在潜在的间隙(为了对齐)[1]
void function_1(){
struct rectangle my_rec;
// 通过 . 来访问结构中的数据
my_rec.width = 10;
my_rec.height = 20;
// 你也可以声明指向结构体的指针
struct rectangle *my_rec_ptr = &my_rec;
// 通过取消引用来改变结构体的成员...
(*my_rec_ptr).width = 30;
// ... 或者用 -> 操作符作为简写提高可读性
my_rec_ptr->height = 10; // Same as (*my_rec_ptr).height = 10;
}
// 你也可以用typedef来给一个结构体起一个别名
typedef struct rectangle rect;
int area(rect r){
return r.width * r.height;
}
// 如果struct较大,你可以通过指针传递,避免
// 复制整个struct。
int area(const rect *r)
{
return r->width * r->height;
}
///////////////////////////////////////
// 函数指针
///////////////////////////////////////
/*
在运行时,函数本身也被存放到某块内存区域当中
函数指针就像其他指针一样(不过是存储一个内存地址) 但却可以被用来直接调用函数,
并且可以四处传递回调函数
但是,定义的语法初看令人有些迷惑
例子:通过指针调用str_reverse
*/
void str_reverse_through_pointer(char *str_in) {
// 定义一个函数指针 f.
void (*f)(char *); // 签名一定要与目标函数相同
f = &str_reverse; // 将函数的地址在运行时赋给指针
(*f)(str_in); // 通过指针调用函数
// f(str_in); // 等价于这种调用方式
}
/*
只要函数签名是正确的,任何时候都能将任何函数赋给某个函数指针
为了可读性和简洁性,函数指针经常和typedef搭配使用:
*/
typedef void (*my_fnp_type)(char *);
// 实际声明函数指针会这么用:
// ...
// my_fnp_type f;
// 特殊字符
'\a' // bell
'\n' // 换行
'\t' // tab
'\v' // vertical tab
'\f' // formfeed
'\r' // 回车
'\b' // 退格
'\0' // null,通常置于字符串的最后。
// hello\n\0. 按照惯例,\0用于标记字符串的末尾。
'\\' // 反斜杠
'\?' // 问号
'\'' // 单引号
'\"' // 双引号
'\xhh' // 十六进制数字. 例子: '\xb' = vertical tab
'\ooo' // 八进制数字. 例子: '\013' = vertical tab
// 打印格式:
"%d" // 整数
"%3d" // 3位以上整数 (右对齐文本)
"%s" // 字符串
"%f" // float
"%ld" // long
"%3.2f" // 左3位以上、右2位以上十进制浮
"%7.4s" // (字符串同样适用)
"%c" // 字母
"%p" // 指针
"%x" // 十六进制
"%o" // 八进制
"%%" // 打印 %
///////////////////////////////////////
// 演算优先级
///////////////////////////////////////
//---------------------------------------------------//
// 操作符 | 组合 //
//---------------------------------------------------//
// () [] -> . | 从左到右 //
// ! ~ ++ -- + = *(type)sizeof | 从右到左 //
// * / % | 从左到右 //
// + - | 从左到右 //
// << >> | 从左到右 //
// < <= > >= | 从左到右 //
// == != | 从左到右 //
// & | 从左到右 //
// ^ | 从左到右 //
// | | 从左到右 //
// && | 从左到右 //
// || | 从左到右 //
// ?: | 从右到左 //
// = += -= *= /= %= &= ^= |= <<= >>= | 从右到左 //
// , | 从左到右 //
//---------------------------------------------------//
================================================
FILE: learncsharp-cn.cs
================================================
// 单行注释以 // 开始
/*
多行注释是这样的
*/
/// <summary>
/// XML文档注释
/// </summary>
// 声明应用用到的命名空间
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Dynamic;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Threading.Tasks;
using System.IO;
// 定义作用域,将代码组织成包
namespace Learning
{
// 每个 .cs 文件至少需要包含一个和文件名相同的类
// 你可以不这么干,但是这样不好。
public class LearnCSharp
{
// 基本语法 - 如果你以前用过 Java 或 C++ 的话,可以直接跳到后文「有趣的特性」
public static void Syntax()
{
// 使用 Console.WriteLine 打印信息
Console.WriteLine("Hello World");
Console.WriteLine(
"Integer: " + 10 +
" Double: " + 3.14 +
" Boolean: " + true);
// 使用 Console.Write 打印,不带换行符号
Console.Write("Hello ");
Console.Write("World");
///////////////////////////////////////////////////
// 类型和变量
//
// 使用 <type> <name> 定义变量
///////////////////////////////////////////////////
// Sbyte - 有符号 8-bit 整数
// (-128 <= sbyte <= 127)
sbyte fooSbyte = 100;
// Byte - 无符号 8-bit 整数
// (0 <= byte <= 255)
byte fooByte = 100;
// Short - 16-bit 整数
// 有符号 - (-32,768 <= short <= 32,767)
// 无符号 - (0 <= ushort <= 65,535)
short fooShort = 10000;
ushort fooUshort = 10000;
// Integer - 32-bit 整数
int fooInt = 1; // (-2,147,483,648 <= int <= 2,147,483,647)
uint fooUint = 1; // (0 <= uint <= 4,294,967,295)
// Long - 64-bit 整数
long fooLong = 100000L; // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807)
ulong fooUlong = 100000L; // (0 <= ulong <= 18,446,744,073,709,551,615)
// 数字默认为 int 或 uint (取决于尺寸)
// 使用 L 标明变量值类型为long 或 ulong
// Double - 双精度 64-bit IEEE 754 浮点数
double fooDouble = 123.4; // 精度: 15-16 位
// Float - 单精度 32-bit IEEE 754 浮点数
float fooFloat = 234.5f; // 精度: 7 位
// 使用 f 标明变量值类型为float
// Decimal - 128-bits 数据类型,比其他浮点类型精度更高
// 适合财务、金融
decimal fooDecimal = 150.3m;
// 布尔值 - true & false
bool fooBoolean = true; // 或 false
// Char - 单个 16-bit Unicode 字符
char fooChar = 'A';
// 字符串 -- 和前面的基本类型不同,字符串不是值,而是引用。
// 这意味着你可以将字符串设为null。
string fooString = "\"escape\" quotes and add \n (new lines) and \t (tabs)";
Console.WriteLine(fooString);
// 你可以通过索引访问字符串的每个字符:
char charFromString = fooString[1]; // => 'e'
// 字符串不可修改: fooString[1] = 'X' 是行不通的;
// 根据当前的locale设定比较字符串,大小写不敏感
string.Compare(fooString, "x", StringComparison.CurrentCultureIgnoreCase);
// 基于sprintf的字符串格式化
string fooFs = string.Format("Check Check, {0} {1}, {0} {1:0.0}", 1, 2);
// 日期和格式
DateTime fooDate = DateTime.Now;
Console.WriteLine(fooDate.ToString("hh:mm, dd MMM yyyy"));
// 使用 @ 符号可以创建跨行的字符串。使用 "" 来表示 "
string bazString = @"Here's some stuff
on a new line! ""Wow!"", the masses cried";
// 使用const或read-only定义常量
// 常量在编译期演算
const int HOURS_I_WORK_PER_WEEK = 9001;
///////////////////////////////////////////////////
// 数据结构
///////////////////////////////////////////////////
// 数组 - 从0开始计数
// 声明数组时需要确定数组长度
// 声明数组的格式如下:
// <datatype>[] <var name> = new <datatype>[<array size>];
int[] intArray = new int[10];
// 声明并初始化数组的其他方式:
int[] y = { 9000, 1000, 1337 };
// 访问数组的元素
Console.WriteLine("intArray @ 0: " + intArray[0]);
// 数组可以修改
intArray[1] = 1;
// 列表
// 列表比数组更常用,因为列表更灵活。
// 声明列表的格式如下:
// List<datatype> <var name> = new List<datatype>();
List<int> intList = new List<int>();
List<string> stringList = new List<string>();
List<int> z = new List<int> { 9000, 1000, 1337 }; // i
// <>用于泛型 - 参考下文
// 列表无默认值
// 访问列表元素时必须首先添加元素
intList.Add(1);
Console.WriteLine("intList @ 0: " + intList[0]);
// 其他数据结构:
// 堆栈/队列
// 字典 (哈希表的实现)
// 哈希集合
// 只读集合
// 元组 (.Net 4+)
///////////////////////////////////////
// 操作符
///////////////////////////////////////
Console.WriteLine("\n->Operators");
int i1 = 1, i2 = 2; // 多重声明的简写形式
// 算术直截了当
Console.WriteLine(i1 + i2 - i1 * 3 / 7); // => 3
// 取余
Console.WriteLine("11%3 = " + (11 % 3)); // => 2
// 比较操作符
Console.WriteLine("3 == 2? " + (3 == 2)); // => false
Console.WriteLine("3 != 2? " + (3 != 2)); // => true
Console.WriteLine("3 > 2? " + (3 > 2)); // => true
Console.WriteLine("3 < 2? " + (3 < 2)); // => false
Console.WriteLine("2 <= 2? " + (2 <= 2)); // => true
Console.WriteLine("2 >= 2? " + (2 >= 2)); // => true
// 位操作符
/*
~ 取反
<< 左移(有符号)
>> 右移(有符号)
& 与
^ 异或
| 或
*/
// 自增、自减
int i = 0;
Console.WriteLine("\n->Inc/Dec-rementation");
Console.WriteLine(i++); //i = 1. 事后自增
Console.WriteLine(++i); //i = 2. 事先自增
Console.WriteLine(i--); //i = 1. 事后自减
Console.WriteLine(--i); //i = 0. 事先自减
///////////////////////////////////////
// 控制结构
///////////////////////////////////////
Console.WriteLine("\n->Control Structures");
// 类似C的if语句
int j = 10;
if (j == 10)
{
Console.WriteLine("I get printed");
}
else if (j > 10)
{
Console.WriteLine("I don't");
}
else
{
Console.WriteLine("I also don't");
}
// 三元表达式
// 简单的 if/else 语句可以写成:
// <条件> ? <真> : <假>
string isTrue = (true) ? "True" : "False";
// While 循环
int fooWhile = 0;
while (fooWhile < 100)
{
//迭代 100 次, fooWhile 0->99
fooWhile++;
}
// Do While 循环
int fooDoWhile = 0;
do
{
//迭代 100 次, fooDoWhile 0->99
fooDoWhile++;
} while (fooDoWhile < 100);
//for 循环结构 => for(<初始条件>; <条件>; <步>)
for (int fooFor = 0; fooFor < 10; fooFor++)
{
//迭代10次, fooFor 0->9
}
// foreach循环
// foreach 循环结构 => foreach(<迭代器类型> <迭代器> in <可枚举结构>)
// foreach 循环适用于任何实现了 IEnumerable 或 IEnumerable<T> 的对象。
// .Net 框架下的集合类型(数组, 列表, 字典...)
// 都实现了这些接口
// (下面的代码中,ToCharArray()可以删除,因为字符串同样实现了IEnumerable)
foreach (char character in "Hello World".ToCharArray())
{
//迭代字符串中的所有字符
}
// Switch 语句
// switch 适用于 byte、short、char和int 数据类型。
// 同样适用于可枚举的类型
// 包括字符串类, 以及一些封装了原始值的类:
// Character、Byte、Short和Integer。
int month = 3;
string monthString;
switch (month)
{
case 1:
monthString = "January";
break;
case 2:
monthString = "February";
break;
case 3:
monthString = "March";
break;
// 你可以一次匹配多个case语句
// 但是你在添加case语句后需要使用break
// (否则你需要显式地使用goto case x语句)
case 6:
case 7:
case 8:
monthString = "Summer time!!";
break;
default:
monthString = "Some other month";
break;
}
///////////////////////////////////////
// 转换、指定数据类型
///////////////////////////////////////
// 转换类型
// 转换字符串为整数
// 转换失败会抛出异常
int.Parse("123");//返回整数类型的"123"
// TryParse会尝试转换类型,失败时会返回缺省类型
// 例如 0
int tryInt;
if (int.TryParse("123", out tryInt)) // Funciton is boolean
Console.WriteLine(tryInt); // 123
// 转换整数为字符串
// Convert类提供了一系列便利转换的方法
Convert.ToString(123);
// or
tryInt.ToString();
}
///////////////////////////////////////
// 类
///////////////////////////////////////
public static void Classes()
{
// 参看文件尾部的对象声明
// 使用new初始化对象
Bicycle trek = new Bicycle();
// 调用对象的方法
trek.SpeedUp(3); // 你应该一直使用setter和getter方法
trek.Cadence = 100;
// 查看对象的信息.
Console.WriteLine("trek info: " + trek.Info());
// 实例化一个新的Penny Farthing
PennyFarthing funbike = new PennyFarthing(1, 10);
Console.WriteLine("funbike info: " + funbike.Info());
Console.Read();
} // 结束main方法
// 终端程序 终端程序必须有一个main方法作为入口
public static void Main(string[] args)
{
OtherInterestingFeatures();
}
//
// 有趣的特性
//
// 默认方法签名
public // 可见性
static // 允许直接调用类,无需先创建实例
int, //返回值
MethodSignatures(
int maxCount, // 第一个变量,类型为整型
int count = 0, // 如果没有传入值,则缺省值为0
int another = 3,
params string[] otherParams // 捕获其他参数
)
{
return -1;
}
// 方法可以重名,只要签名不一样
public static void MethodSignature(string maxCount)
{
}
//泛型
// TKey和TValue类由用用户调用函数时指定。
// 以下函数模拟了Python的SetDefault
public static TValue SetDefault<TKey, TValue>(
IDictionary<TKey, TValue> dictionary,
TKey key,
TValue defaultItem)
{
TValue result;
if (!dictionary.TryGetValue(key, out result))
return dictionary[key] = defaultItem;
return result;
}
// 你可以限定传入值的范围
public static void IterateAndPrint<T>(T toPrint) where T: IEnumerable<int>
{
// 我们可以进行迭代,因为T是可枚举的
foreach (var item in toPrint)
// ittm为整数
Console.WriteLine(item.ToString());
}
public static void OtherInterestingFeatures()
{
// 可选参数
MethodSignatures(3, 1, 3, "Some", "Extra", "Strings");
MethodSignatures(3, another: 3); // 显式指定参数,忽略可选参数
// 扩展方法
int i = 3;
i.Print(); // 参见下面的定义
// 可为null的类型 对数据库交互、返回值很有用
// 任何值类型 (i.e. 不为类) 添加后缀 ? 后会变为可为null的值
// <类型>? <变量名> = <值>
int? nullable = null; // Nullable<int> 的简写形式
Console.WriteLine("Nullable variable: " + nullable);
bool hasValue = nullable.HasValue; // 不为null时返回真
// ?? 是用于指定默认值的语法糖
// 以防变量为null的情况
int notNullable = nullable ?? 0; // 0
// 变量类型推断 - 你可以让编译器推断变量类型:
var magic = "编译器确定magic是一个字符串,所以仍然是类型安全的";
// magic = 9; // 不工作,因为magic是字符串,而不是整数。
// 泛型
//
var phonebook = new Dictionary<string, string>() {
{"Sarah", "212 555 5555"} // 在电话簿中加入新条目
};
// 调用上面定义为泛型的SETDEFAULT
Console.WriteLine(SetDefault<string,string>(phonebook, "Shaun", "No Phone")); // 没有电话
// 你不用指定TKey、TValue,因为它们会被隐式地推导出来
Console.WriteLine(SetDefault(phonebook, "Sarah", "No Phone")); // 212 555 5555
// lambda表达式 - 允许你用一行代码搞定函数
Func<int, int> square = (x) => x * x; // 最后一项为返回值
Console.WriteLine(square(3)); // 9
// 可抛弃的资源管理 - 让你很容易地处理未管理的资源
// 大多数访问未管理资源 (文件操作符、设备上下文, etc.)的对象
// 都实现了IDisposable接口。
// using语句会为你清理IDisposable对象。
using (StreamWriter writer = new StreamWriter("log.txt"))
{
writer.WriteLine("这里没有什么可疑的东西");
// 在作用域的结尾,资源会被回收
// (即使有异常抛出,也一样会回收)
}
// 并行框架
// http://blogs.msdn.com/b/csharpfaq/archive/2010/06/01/parallel-programming-in-net-framework-4-getting-started.aspx
var websites = new string[] {
"http://www.google.com", "http://www.reddit.com",
"http://www.shaunmccarthy.com"
};
var responses = new Dictionary<string, string>();
// 为每个请求新开一个线程
// 在运行下一步前合并结果
Parallel.ForEach(websites,
new ParallelOptions() {MaxDegreeOfParallelism = 3}, // max of 3 threads
website =>
{
// Do something that takes a long time on the file
using (var r = WebRequest.Create(new Uri(website)).GetResponse())
{
responses[website] = r.ContentType;
}
});
// 直到所有的请求完成后才会运行下面的代码
foreach (var key in responses.Keys)
Console.WriteLine("{0}:{1}", key, responses[key]);
// 动态对象(配合其他语言使用很方便)
dynamic student = new ExpandoObject();
student.FirstName = "First Name"; // 不需要先定义类!
// 你甚至可以添加方法(接受一个字符串,输出一个字符串)
student.Introduce = new Func<string, string>(
(introduceTo) => string.Format("Hey {0}, this is {1}", student.FirstName, introduceTo));
Console.WriteLine(student.Introduce("Beth"));
// IQUERYABLE<T> - 几乎所有的集合都实现了它,
// 带给你 Map / Filter / Reduce 风格的方法
var bikes = new List<Bicycle>();
bikes.Sort(); // Sorts the array
bikes.Sort((b1, b2) => b1.Wheels.CompareTo(b2.Wheels)); // 根据车轮数排序
var result = bikes
.Where(b => b.Wheels > 3) // 筛选 - 可以连锁使用 (返回IQueryable)
.Where(b => b.IsBroken && b.HasTassles)
.Select(b => b.ToString()); // Map - 这里我们使用了select,所以结果是IQueryable<string>
var sum = bikes.Sum(b => b.Wheels); // Reduce - 计算集合中的轮子总数
// 创建一个包含基于自行车的一些参数生成的隐式对象的列表
var bikeSummaries = bikes.Select(b=>new { Name = b.Name, IsAwesome = !b.IsBroken && b.HasTassles });
// 很难演示,但是编译器在代码编译完成前就能推导出以上对象的类型
foreach (var bikeSummary in bikeSummaries.Where(b => b.IsAwesome))
Console.WriteLine(bikeSummary.Name);
// ASPARALLEL
// 邪恶的特性 —— 组合了linq和并行操作
var threeWheelers = bikes.AsParallel().Where(b => b.Wheels == 3).Select(b => b.Name);
// 以上代码会并发地运行。会自动新开线程,分别计算结果。
// 适用于多核、大数据量的场景。
// LINQ - 将IQueryable<T>映射到存储,延缓执行
// 例如 LinqToSql 映射数据库, LinqToXml 映射XML文档
var db = new BikeRespository();
// 执行被延迟了,这对于查询数据库来说很好
var filter = db.Bikes.Where(b => b.HasTassles); // 不运行查询
if (42 > 6) // 你可以不断地增加筛选,包括有条件的筛选,例如用于“高级搜索”功能
filter = filter.Where(b => b.IsBroken); // 不运行查询
var query = filter
.OrderBy(b => b.Wheels)
.ThenBy(b => b.Name)
.Select(b => b.Name); // 仍然不运行查询
// 现在运行查询,运行查询的时候会打开一个读取器,所以你迭代的是一个副本
foreach (string bike in query)
Console.WriteLine(result);
}
} // 结束LearnCSharp类
// 你可以在同一个 .cs 文件中包含其他类
public static class Extensions
{
// 扩展函数
public static void Print(this object obj)
{
Console.WriteLine(obj.ToString());
}
}
// 声明类的语法:
// <public/private/protected/internal> class <类名>{
// //数据字段, 构造器, 内部函数.
/ // 在Java中函数被称为方法。
// }
public class Bicycle
{
// 自行车的字段、变量
public int Cadence // Public: 任何地方都可以访问
{
get // get - 定义获取属性的方法
{
return _cadence;
}
set // set - 定义设置属性的方法
{
_cadence = value; // value是被传递给setter的值
}
}
private int _cadence;
protected virtual int Gear // 类和子类可以访问
{
get; // 创建一个自动属性,无需成员字段
set;
}
internal int Wheels // Internal:在同一程序集内可以访问
{
get;
private set; // 可以给get/set方法添加修饰符
}
int _speed; // 默认为private: 只可以在这个类内访问,你也可以使用`private`关键词
public string Name { get; set; }
// enum类型包含一组常量
// 它将名称映射到值(除非特别说明,是一个整型)
// enmu元素的类型可以是byte、sbyte、short、ushort、int、uint、long、ulong。
// enum不能包含相同的值。
public enum BikeBrand
{
AIST,
BMC,
Electra = 42, //你可以显式地赋值
Gitane // 43
}
// 我们在Bicycle类中定义的这个类型,所以它是一个内嵌类型。
// 这个类以外的代码应当使用`Bicycle.Brand`来引用。
public BikeBrand Brand; // 声明一个enum类型之后,我们可以声明这个类型的字段
// 静态方法的类型为自身,不属于特定的对象。
// 你无需引用对象就可以访问他们。
// Console.WriteLine("Bicycles created: " + Bicycle.bicyclesCreated);
static public int BicyclesCreated = 0;
// 只读值在运行时确定
// 它们只能在声明或构造器内被赋值
readonly bool _hasCardsInSpokes = false; // read-only private
// 构造器是创建类的一种方式
// 下面是一个默认的构造器
public Bicycle()
{
this.Gear = 1; // 你可以使用关键词this访问对象的成员
Cadence = 50; // 不过你并不总是需要它
_speed = 5;
Name = "Bontrager";
Brand = BikeBrand.AIST;
BicyclesCreated++;
}
// 另一个构造器的例子(包含参数)
public Bicycle(int startCadence, int startSpeed, int startGear,
string name, bool hasCardsInSpokes, BikeBrand brand)
: base() // 首先调用base
{
Gear = startGear;
Cadence = startCadence;
_speed = startSpeed;
Name = name;
_hasCardsInSpokes = hasCardsInSpokes;
Brand = brand;
}
// 构造器可以连锁使用
public Bicycle(int startCadence, int startSpeed, BikeBrand brand) :
this(startCadence, startSpeed, 0, "big wheels", true, brand)
{
}
// 函数语法
// <public/private/protected> <返回值> <函数名称>(<参数>)
// 类可以为字段实现 getters 和 setters 方法 for their fields
// 或者可以实现属性(C#推荐使用这个)
// 方法的参数可以有默认值
// 在有默认值的情况下,调用方法的时候可以省略相应的参数
public void SpeedUp(int increment = 1)
{
_speed += increment;
}
public void SlowDown(int decrement = 1)
{
_speed -= decrement;
}
// 属性可以访问和设置值
// 当只需要访问数据的时候,考虑使用属性。
// 属性可以定义get和set,或者是同时定义两者
private bool _hasTassles; // private variable
public bool HasTassles // public accessor
{
get { return _hasTassles; }
set { _hasTassles = value; }
}
// 你可以在一行之内定义自动属性
// 这个语法会自动创建后备字段
// 你可以给getter或setter设置访问修饰符
// 以便限制它们的访问
public bool IsBroken { get; private set; }
// 属性的实现可以是自动的
public int FrameSize
{
get;
// 你可以给get或set指定访问修饰符
// 以下代码意味着只有Bicycle类可以调用Framesize的set
private set;
}
//显示对象属性的方法
public virtual string Info()
{
return "Gear: " + Gear +
" Cadence: " + Cadence +
" Speed: " + _speed +
" Name: " + Name +
" Cards in Spokes: " + (_hasCardsInSpokes ? "yes" : "no") +
"\n------------------------------\n"
;
}
// 方法可以是静态的。通常用于辅助方法。
public static bool DidWeCreateEnoughBycles()
{
// 在静态方法中,你只能引用类的静态成员
return BicyclesCreated > 9000;
} // 如果你的类只需要静态成员,考虑将整个类作为静态类。
} // Bicycle类结束
// PennyFarthing是Bicycle的一个子类
class PennyFarthing : Bicycle
{
// (Penny Farthings是一种前轮很大的自行车。没有齿轮。)
// 调用父构造器
public PennyFarthing(int startCadence, int startSpeed) :
base(startCadence, startSpeed, 0, "PennyFarthing", true, BikeBrand.Electra)
{
}
protected override int Gear
{
get
{
return 0;
}
set
{
throw new ArgumentException("你不可能在PennyFarthing上切换齿轮");
}
}
public override string Info()
{
string result = "PennyFarthing bicycle ";
result += base.ToString(); // 调用父方法
return result;
}
}
// 接口只包含成员的签名,而没有实现。
interface IJumpable
{
void Jump(int meters); // 所有接口成员是隐式地公开的
}
interface IBreakable
{
bool Broken { get; } // 接口可以包含属性、方法和事件
}
// 类只能继承一个类,但是可以实现任意数量的接口
{
int damage = 0;
public void Jump(int meters)
{
damage += meters;
}
public bool Broken
{
get
{
return damage > 100;
}
}
}
/// <summary>
/// 连接数据库,一个 LinqToSql的示例。
/// EntityFramework Code First 很棒 (类似 Ruby的 ActiveRecord, 不过是双向的)
/// http://msdn.microsoft.com/en-us/data/jj193542.aspx
/// </summary>
public class BikeRespository : DbSet
{
public BikeRespository()
: base()
{
}
public DbSet<Bicycle> Bikes { get; set; }
}
} // 结束 Namespace
================================================
FILE: learncss-cn.css
================================================
/* 注释 */
/* ####################
## 选择器
####################*/
/* 一般而言,CSS的声明语句非常简单。 */
选择器 { 属性: 值; /* 更多属性...*/ }
/* 选择器用于指定页面上的元素。
针对页面上的所有元素。 */
* { color:red; }
/*
假定页面上有这样一个元素
<div class='some-class class2' id='someId' attr='value' />
*/
/* 你可以通过类名来指定它 */
.some-class { }
/* 给出所有类名 */
.some-class.class2 { }
/* 标签名 */
div { }
/* id */
#someId { }
/* 由于元素包含attr属性,因此也可以通过这个来指定 */
[attr] { font-size:smaller; }
/* 以及有特定值的属性 */
[attr='value'] { font-size:smaller; }
/* 通过属性的值的开头指定 */
[attr^='val'] { font-size:smaller; }
/* 通过属性的值的结尾来指定 */
[attr$='ue'] { font-size:smaller; }
/* 通过属性的值的部分来指定 */
[attr~='lu'] { font-size:smaller; }
/* 你可以把这些全部结合起来,注意不同部分间不应该有空格,否则会改变语义 */
div.some-class[attr$='ue'] { }
/* 你也可以通过父元素来指定。*/
/* 某个元素是另一个元素的直接子元素 */
div.some-parent > .class-name {}
/* 或者通过该元素的祖先元素 */
div.some-parent .class-name {}
/* 注意,去掉空格后语义就不同了。
你能说出哪里不同么? */
div.some-parent.class-name {}
/* 你可以选择某元素前的相邻元素 */
.i-am-before + .this-element { }
/* 某元素之前的同级元素(相邻或不相邻) */
.i-am-any-before ~ .this-element {}
/* 伪类允许你基于页面的行为指定元素(而不是基于页面结构) */
/* 例如,当鼠标悬停在某个元素上时 */
:hover {}
/* 已访问过的链接*/
:visited {}
/* 未访问过的链接*/
:link {}
/* 当前焦点的input元素 */
:focus {}
/* ####################
## 属性
####################*/
选择器 {
/* 单位 */
width: 50%; /* 百分比 */
font-size: 2em; /* 当前字体大小的两倍 */
width: 200px; /* 像素 */
font-size: 20pt; /* 点 */
width: 5cm; /* 厘米 */
width: 50mm; /* 毫米 */
width: 5in; /* 英尺 */
/* 颜色 */
background-color: #F6E; /* 短16位 */
background-color: #F262E2; /* 长16位 */
background-color: tomato; /* 颜色名称 */
background-color: rgb(255, 255, 255); /* rgb */
background-color: rgb(10%, 20%, 50%); /* rgb 百分比 */
background-color: rgba(255, 0, 0, 0.3); /* rgb 加透明度 */
/* 图片 */
background-image: url(/path-to-image/image.jpg);
/* 字体 */
font-family: Arial;
font-family: "Courier New"; /* 使用双引号包裹含空格的字体名称 */
font-family: "Courier New", Trebuchet, Arial; /* 如果第一个
字体没找到,浏览器会使用第二个字体,一次类推 */
}
<!-- 你需要在文件的 <head> 引用CSS文件 -->
<link rel='stylesheet' type='text/css' href='filepath/filename.css' />
<!-- 你也可以在标记中内嵌CSS。不过强烈建议不要这么干。 -->
<style>
选择器 { 属性:值; }
</style>
<!-- 也可以直接使用元素的style属性。
这是你最不该干的事情。 -->
<div style='property:value;'>
</div>
/*A*/
p.class1[attr='value']
/*B*/
p.class1 {}
/*C*/
p.class2 {}
/*D*/
p {}
/*E*/
p { property: value !important; }
<p style='/*F*/ property:value;' class='class1 class2' attr='value'>
</p>
================================================
FILE: learngo-cn.go
================================================
// 单行注释
/* 多行
注释 */
// 导入包的子句在每个源文件的开头。
// Main比较特殊,它用来声明可执行文件,而不是一个库。
package main
// Import语句声明了当前文件引用的包。
import (
"fmt" // Go语言标准库中的包
"net/http" // 一个web服务器包
"strconv" // 字符串转换
)
// 函数声明:Main是程序执行的入口。
// 不管你喜欢还是不喜欢,反正Go就用了花括号来包住函数体。
func main() {
// 往标准输出打印一行。
// 用包名fmt限制打印函数。
fmt.Println("Hello world!")
// 调用当前包的另一个函数。
beyondHello()
}
// 函数可以在括号里加参数。
// 如果没有参数的话,也需要一个空括号。
func beyondHello() {
var x int // 变量声明,变量必须在使用之前声明。
x = 3 // 变量赋值。
// 可以用:=来偷懒,它自动把变量类型、声明和赋值都搞定了。
y := 4
sum, prod := learnMultiple(x, y) // 返回多个变量的函数
fmt.Println("sum:", sum, "prod:", prod) // 简单输出
learnTypes() // 少于y分钟,学的更多!
}
// 多变量和多返回值的函数
func learnMultiple(x, y int) (sum, prod int) {
return x + y, x * y // 返回两个值
}
// 内置变量类型和关键词
func learnTypes() {
// 短声明给你所想。
s := "Learn Go!" // String类型
s2 := `A "raw" string literal
can include line breaks.` // 同样是String类型
// 非ascii字符。Go使用UTF-8编码。
g := 'Σ' // rune类型,int32的别名,使用UTF-8编码
f := 3.14195 // float64类型,IEEE-754 64位浮点数
c := 3 + 4i // complex128类型,内部使用两个float64表示
// Var变量可以直接初始化。
var u uint = 7 // unsigned 无符号变量,但是实现依赖int型变量的长度
var pi float32 = 22. / 7
// 字符转换
n := byte('\n') // byte是uint8的别名
// 数组类型编译的时候大小固定。
var a4 [4] int // 有4个int变量的数组,初始为0
a3 := [...]int{3, 1, 5} // 有3个int变量的数组,同时进行了初始化
// Slice 可以动态的增删。Array和Slice各有千秋,但是使用slice的地方更多些。
s3 := []int{4, 5, 9} // 和a3相比,这里没有省略号
s4 := make([]int, 4) // 分配一个有4个int型变量的slice,全部被初始化为0
var d2 [][]float64 // 声明而已,什么都没有分配
bs := []byte("a slice") // 类型转换的语法
p, q := learnMemory() // 声明p,q为int型变量的指针
fmt.Println(*p, *q) // * 取值
// Map是动态可增长关联数组,和其他语言中的hash或者字典相似。
m := map[string]int{"three": 3, "four": 4}
m["one"] = 1
// 在Go语言中未使用的变量在编译的时候会报错,而不是warning。
// 下划线 _ 可以使你“使用”一个变量,但是丢弃它的值。
_,_,_,_,_,_,_,_,_ = s2, g, f, u, pi, n, a3, s4, bs
// 输出变量
fmt.Println(s, c, a4, s3, d2, m)
learnFlowControl() // 回到流程控制
}
// Go全面支持垃圾回收。Go有指针,但是不支持指针运算。
// 你会因为空指针而犯错,但是不会因为增加指针而犯错。
func learnMemory() (p, q *int) {
// 返回int型变量指针p和q
p = new(int) // 内置函数new分配内存
// 自动将分配的int赋值0,p不再是空的了。
s := make([]int, 20) // 给20个int变量分配一块内存
s[3] = 7 // 赋值
r := -2 // 声明另一个局部变量
return &s[3], &r // & 取地址
}
func expensiveComputation() int {
return 1e6
}
func learnFlowControl() {
// If需要花括号,括号就免了
if true {
fmt.Println("told ya")
}
// 用go fmt 命令可以帮你格式化代码,所以不用怕被人吐槽代码风格了,
// 也不用容忍被人的代码风格。
if false {
// pout
} else {
// gloat
}
// 如果太多嵌套的if语句,推荐使用switch
x := 1
switch x {
case 0:
case 1:
// 隐式调用break语句,匹配上一个即停止
case 2:
// 不会运行
}
// 和if一样,for也不用括号
for x := 0; x < 3; x++ { // ++ 自增
fmt.Println("iteration", x)
}
// x在这里还是1。为什么?
// for 是go里唯一的循环关键字,不过它有很多变种
for { // 死循环
break // 骗你的
continue // 不会运行的
}
// 和for一样,if中的:=先给y赋值,然后再和x作比较。
if y := expensiveComputation(); y > x {
x = y
}
// 闭包函数
xBig := func() bool {
return x > 100 // x是上面声明的变量引用
}
fmt.Println("xBig:", xBig()) // true (上面把y赋给x了)
x /= 1e5 // x变成10
fmt.Println("xBig:", xBig()) // 现在是false
// 当你需要goto的时候,你会爱死它的!
goto love
love:
learnInterfaces() // 好东西来了!
}
// 定义Stringer为一个接口类型,有一个方法String
type Stringer interface {
String() string
}
// 定义pair为一个结构体,有x和y两个int型变量。
type pair struct {
x, y int
}
// 定义pair类型的方法,实现Stringer接口。
func (p pair) String() string { // p被叫做“接收器”
// Sprintf是fmt包中的另一个公有函数。
// 用 . 调用p中的元素。
return fmt.Sprintf("(%d, %d)", p.x, p.y)
}
func learnInterfaces() {
// 花括号用来定义结构体变量,:=在这里将一个结构体变量赋值给p。
p := pair{3, 4}
fmt.Println(p.String()) // 调用pair类型p的String方法
var i Stringer // 声明i为Stringer接口类型
i = p // 有效!因为p实现了Stringer接口(类似java中的塑型)
// 调用i的String方法,输出和上面一样
fmt.Println(i.String())
// fmt包中的Println函数向对象要它们的string输出,实现了String方法就可以这样使用了。
// (类似java中的序列化)
fmt.Println(p) // 输出和上面一样,自动调用String函数。
fmt.Println(i) // 输出和上面一样。
learnErrorHandling()
}
func learnErrorHandling() {
// ", ok"用来判断有没有正常工作
m := map[int]string{3: "three", 4: "four"}
if x, ok := m[1]; !ok { // ok 为false,因为m中没有1
fmt.Println("no one there")
} else {
fmt.Print(x) // 如果x在map中的话,x就是那个值喽。
}
// 错误可不只是ok,它还可以给出关于问题的更多细节。
if _, err := strconv.Atoi("non-int"); err != nil { // _ discards value
// 输出"strconv.ParseInt: parsing "non-int": invalid syntax"
fmt.Println(err)
}
// 待会再说接口吧。同时,
learnConcurrency()
}
// c是channel类型,一个并发安全的通信对象。
func inc(i int, c chan int) {
c <- i + 1 // <-把右边的发送到左边的channel。
}
// 我们将用inc函数来并发地增加一些数字。
func learnConcurrency() {
// 用make来声明一个slice,make会分配和初始化slice,map和channel。
c := make(chan int)
// 用go关键字开始三个并发的goroutine,如果机器支持的话,还可能是并行执行。
// 三个都被发送到同一个channel。
go inc(0, c) // go is a statement that starts a new goroutine.
go inc(10, c)
go inc(-805, c)
// 从channel中独处结果并打印。
// 打印出什么东西是不可预知的。
fmt.Println(<-c, <-c, <-c) // channel在右边的时候,<-是读操作。
cs := make(chan string) // 操作string的channel
cc := make(chan chan string) // 操作channel的channel
go func() { c <- 84 }() // 开始一个goroutine来发送一个新的数字
go func() { cs <- "wordy" }() // 发送给cs
// Select类似于switch,但是每个case包括一个channel操作。
// 它随机选择一个准备好通讯的case。
select {
case i := <-c: // 从channel接收的值可以赋给其他变量
fmt.Println("it's a", i)
case <-cs: // 或者直接丢弃
fmt.Println("it's a string")
case <-cc: // 空的,还没作好通讯的准备
fmt.Println("didn't happen.")
}
// 上面c或者cs的值被取到,其中一个goroutine结束,另外一个一直阻塞。
learnWebProgramming() // Go很适合web编程,我知道你也想学!
}
// http包中的一个简单的函数就可以开启web服务器。
func learnWebProgramming() {
// ListenAndServe第一个参数指定了监听端口,第二个参数是一个接口,特定是http.Handler。
err := http.ListenAndServe(":8080", pair{})
fmt.Println(err) // 不要无视错误。
}
// 使pair实现http.Handler接口的ServeHTTP方法。
func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// 使用http.ResponseWriter返回数据
w.Write([]byte("You learned Go in Y minutes!"))
}
================================================
FILE: learnlua-cn.lua
================================================
-- 单行注释以两个连字符开头
--[[
多行注释
--]]
----------------------------------------------------
-- 1. 变量和流程控制
----------------------------------------------------
num = 42 -- 所有的数字都是双精度浮点型。
-- 别害怕,64位的双精度浮点型数字中有52位用于
-- 保存精确的整型值; 对于52位以内的整型值,
-- 不用担心精度问题。
s = 'walternate' -- 和Python一样,字符串不可变。
t = "也可以用双引号"
u = [[ 多行的字符串
以两个方括号
开始和结尾。]]
t = nil -- 撤销t的定义; Lua 支持垃圾回收。
-- 块使用do/end之类的关键字标识:
while num < 50 do
num = num + 1 -- 不支持 ++ 或 += 运算符。
end
-- If语句:
if num > 40 then
print('over 40')
elseif s ~= 'walternate' then -- ~= 表示不等于。
-- 像Python一样,用 == 检查是否相等 ;字符串同样适用。
io.write('not over 40\n') -- 默认标准输出。
else
-- 默认全局变量。
thisIsGlobal = 5 -- 通常使用驼峰。
-- 如何定义局部变量:
local line = io.read() -- 读取标准输入的下一行。
-- ..操作符用于连接字符串:
print('Winter is coming, ' .. line)
end
-- 未定义的变量返回nil。
-- 这不是错误:
foo = anUnknownVariable -- 现在 foo = nil.
aBoolValue = false
--只有nil和false为假; 0和 ''均为真!
if not aBoolValue then print('false') end
-- 'or'和 'and'短路
-- 类似于C/js里的 a?b:c 操作符:
ans = aBoolValue and 'yes' or 'no' --> 'no'
karlSum = 0
for i = 1, 100 do -- 范围包含两端
karlSum = karlSum + i
end
-- 使用 "100, 1, -1" 表示递减的范围:
fredSum = 0
for j = 100, 1, -1 do fredSum = fredSum + j end
-- 通常,范围表达式为begin, end[, step].
-- 循环的另一种结构:
repeat
print('the way of the future')
num = num - 1
until num == 0
----------------------------------------------------
-- 2. 函数。
----------------------------------------------------
function fib(n)
if n < 2 then return 1 end
return fib(n - 2) + fib(n - 1)
end
-- 支持闭包及匿名函数:
function adder(x)
-- 调用adder时,会创建返回的函数,
-- 并且会记住x的值:
return function (y) return x + y end
end
a1 = adder(9)
a2 = adder(36)
print(a1(16)) --> 25
print(a2(64)) --> 100
-- 返回值、函数调用和赋值都可以
-- 使用长度不匹配的list。
-- 不匹配的接收方会被赋值nil;
-- 不匹配的发送方会被丢弃。
x, y, z = 1, 2, 3, 4
-- x = 1、y = 2、z = 3, 而 4 会被丢弃。
function bar(a, b, c)
print(a, b, c)
return 4, 8, 15, 16, 23, 42
end
x, y = bar('zaphod') --> 打印 "zaphod nil nil"
-- 现在 x = 4, y = 8, 而值15..42被丢弃。
-- 函数是一等公民,可以是局部的,也可以是全局的。
-- 以下表达式等价:
function f(x) return x * x end
f = function (x) return x * x end
-- 这些也是等价的:
local function g(x) return math.sin(x) end
local g; g = function (x) return math.sin(x) end
-- 'local g'使得g可以自引用。
-- 顺便提下,三角函数以弧度为单位。
-- 用一个字符串参数调用函数,可以省略括号:
print 'hello' --可以工作。
-- 调用函数时,如果只有一个table参数,
-- 同样可以省略括号(table详情见下):
print {} -- 一样可以工作。
----------------------------------------------------
-- 3. Table。
----------------------------------------------------
-- Table = Lua唯一的组合数据结构;
-- 它们是关联数组。
-- 类似于PHP的数组或者js的对象,
-- 它们是哈希表或者字典,也可以当列表使用。
-- 按字典/map的方式使用Table:
-- Dict字面量默认使用字符串类型的key:
t = {key1 = 'value1', key2 = false}
-- 字符串key可以使用类似js的点标记:
print(t.key1) -- 打印 'value1'.
t.newKey = {} -- 添加新的键值对。
t.key2 = nil -- 从table删除 key2。
-- 使用任何非nil的值作为key:
u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'}
print(u[6.28]) -- 打印 "tau"
-- 数字和字符串的key按值匹配的
-- table按id匹配。
a = u['@!#'] -- 现在 a = 'qbert'.
b = u[{}] -- 我们或许期待的是 1729, 但是得到的是nil:
-- b = nil ,因为没有找到。
-- 之所以没找到,是因为我们用的key与保存数据时用的不是同
-- 一个对象。
-- 所以字符串和数字是移植性更好的key。
-- 只需要一个table参数的函数调用不需要括号:
function h(x) print(x.key1) end
h{key1 = 'Sonmi~451'} -- 打印'Sonmi~451'.
for key, val in pairs(u) do -- 遍历Table
print(key, val)
end
-- _G 是一个特殊的table,用于保存所有的全局变量
print(_G['_G'] == _G) -- 打印'true'.
-- 按列表/数组的方式使用:
-- 列表字面量隐式添加整数键:
v = {'value1', 'value2', 1.21, 'gigawatts'}
for i = 1, #v do -- #v 是列表的大小
print(v[i]) -- 索引从 1 开始!! 太疯狂了!
end
-- 'list'并非真正的类型,v 其实是一个table,
-- 只不过它用连续的整数作为key,可以像list那样去使用。
----------------------------------------------------
-- 3.1 元表(metatable) 和元方法(metamethod)。
----------------------------------------------------
-- table的元表提供了一种机制,支持类似操作符重载的行为。
-- 稍后我们会看到元表如何支持类似js prototype的行为。
f1 = {a = 1, b = 2} -- 表示一个分数 a/b.
f2 = {a = 2, b = 3}
-- 这会失败:
-- s = f1 + f2
metafraction = {}
function metafraction.__add(f1, f2)
sum = {}
sum.b = f1.b * f2.b
sum.a = f1.a * f2.b + f2.a * f1.b
return sum
end
setmetatable(f1, metafraction)
setmetatable(f2, metafraction)
s = f1 + f2 -- 调用在f1的元表上的__add(f1, f2) 方法
-- f1, f2 没有关于元表的key,这点和js的prototype不一样。
-- 因此你必须用getmetatable(f1)获取元表。
-- 元表是一个普通的table,
-- 元表的key是普通的Lua中的key,例如__add。
-- 但是下面一行代码会失败,因为s没有元表:
-- t = s + s
-- 下面提供的与类相似的模式可以解决这个问题:
-- 元表的__index 可以重载用于查找的点操作符:
defaultFavs = {animal = 'gru', food = 'donuts'}
myFavs = {food = 'pizza'}
setmetatable(myFavs, {__index = defaultFavs})
eatenBy = myFavs.animal -- 可以工作!感谢元表
-- 如果在table中直接查找key失败,会使用
-- 元表的__index 递归地重试。
-- __index的值也可以是function(tbl, key)
-- 这样可以支持自定义查找。
-- __index、__add等的值,被称为元方法。
-- 这里是一个table元方法的清单:
-- __add(a, b) for a + b
-- __sub(a, b) for a - b
-- __mul(a, b) for a * b
-- __div(a, b) for a / b
-- __mod(a, b) for a % b
-- __pow(a, b) for a ^ b
-- __unm(a) for -a
-- __concat(a, b) for a .. b
-- __len(a) for #a
-- __eq(a, b) for a == b
-- __lt(a, b) for a < b
-- __le(a, b) for a <= b
-- __index(a, b) <fn or a table> for a.b
-- __newindex(a, b, c) for a.b = c
-- __call(a, ...) for a(...)
----------------------------------------------------
-- 3.2 与类相似的table和继承。
----------------------------------------------------
-- Lua没有内建的类;可以通过不同的方法,利用表和元表
-- 来实现类。
-- 下面是一个例子,解释在后面:
Dog = {} -- 1.
function Dog:new() -- 2.
newObj = {sound = 'woof'} -- 3.
self.__index = self -- 4.
return setmetatable(newObj, self) -- 5.
end
function Dog:makeSound() -- 6.
print('I say ' .. self.sound)
end
mrDog = Dog:new() -- 7.
mrDog:makeSound() -- 'I say woof' -- 8.
-- 1. Dog看上去像一个类;其实它是一个table。
-- 2. 函数tablename:fn(...) 等价于
-- 函数tablename.fn(self, ...)
-- 冒号(:)只是添加了self作为第一个参数。
-- 阅读7 & 8条 了解self变量是如何得到其值的。
-- 3. newObj是类Dog的一个实例。
-- 4. self = 被继承的类。通常self = Dog,不过继承可以改变它。
-- 如果把newObj的元表和__index都设置为self,
-- newObj就可以得到self的函数。
-- 5. 备忘:setmetatable返回其第一个参数。
-- 6. 冒号(:)的作用和第2条一样,不过这里
-- self是一个实例,而不是类
-- 7. 等价于Dog.new(Dog),所以在new()中,self = Dog。
-- 8. 等价于mrDog.makeSound(mrDog); self = mrDog。
----------------------------------------------------
-- 继承的例子:
LoudDog = Dog:new() -- 1.
function LoudDog:makeSound()
s = self.sound .. ' ' -- 2.
print(s .. s .. s)
end
seymour = LoudDog:new() -- 3.
seymour:makeSound() -- 'woof woof woof' -- 4.
-- 1. LoudDog获得Dog的方法和变量列表。
-- 2. 因为new()的缘故,self拥有了一个'sound' key,参见第3条。
-- 3. 等价于LoudDog.new(LoudDog),转换一下就是
-- Dog.new(LoudDog),这是因为LoudDog没有'new' key,
-- 但是它的元表中有 __index = Dog。
-- 结果: seymour的元表是LoudDog,并且
-- LoudDog.__index = Dog。所以有seymour.key
-- = seymour.key, LoudDog.key, Dog.key
-- 从其中第一个有指定key的table获取。
-- 4. 在LoudDog可以找到'makeSound'的key;
-- 等价于LoudDog.makeSound(seymour)。
-- 如果有必要,子类也可以有new(),与基类相似:
function LoudDog:new()
newObj = {}
-- 初始化newObj
self.__index = self
return setmetatable(newObj, self)
end
----------------------------------------------------
-- 4. 模块
----------------------------------------------------
--[[ 我把这部分给注释了,这样脚本剩下的部分可以运行
-- 假设文件mod.lua的内容类似这样:
local M = {}
local function sayMyName()
print('Hrunkner')
end
function M.sayHello()
print('Why hello there')
sayMyName()
end
return M
-- 另一个文件可以使用mod.lua的功能:
local mod = require('mod') -- 运行文件mod.lua.
-- require是包含模块的标准做法。
-- require等价于: (针对没有被缓存的情况;参见后面的内容)
local mod = (function ()
<contents of mod.lua>
end)()
-- mod.lua被包在一个函数体中,因此mod.lua的局部变量
-- 对外不可见。
-- 下面的代码可以工作,因为在这里mod = mod.lua 中的 M:
mod.sayHello() -- Says hello to Hrunkner.
-- 这是错误的;sayMyName只在mod.lua中存在:
mod.sayMyName() -- 错误
-- require返回的值会被缓存,所以一个文件只会被运行一次,
-- 即使它被require了多次。
-- 假设mod2.lua包含代码"print('Hi!')"。
local a = require('mod2') -- 打印Hi!
local b = require('mod2') -- 不再打印; a=b.
-- dofile与require类似,但是不缓存:
dofile('mod2') --> Hi!
dofile('mod2') --> Hi! (再次运行,与require不同)
-- loadfile加载一个lua文件,但是并不运行它。
f = loadfile('mod2') -- Calling f() runs mod2.lua.
-- loadstring是loadfile的字符串版本。
g = loadstring('print(343)') --返回一个函数。
g() -- 打印343; 在此之前什么也不打印。
--]]
================================================
FILE: learnperl-cn.pl
================================================
# 单行注释以#号开头
#### Perl的变量类型
# 变量以$号开头。
# 合法变量名以英文字母或者下划线起始,
# 后接任意数目的字母、数字或下划线。
### Perl有三种主要的变量类型:标量、数组和哈希。
## 标量
# 标量类型代表单个值:
my $animal = "camel";
my $answer = 42;
# 标量类型值可以是字符串、整型或浮点类型,Perl会根据需要自动进行类型转换。
## 数组
# 数组类型代表一列值:
my @animals = ("camel", "llama", "owl");
my @numbers = (23, 42, 69);
my @mixed = ("camel", 42, 1.23);
## 哈希
# 哈希类型代表一个键/值对的集合:
my %fruit_color = ("apple", "red", "banana", "yellow");
# 可以使用空格和“=>”操作符更清晰的定义哈希:
my %fruit_color = (
apple => "red",
banana => "yellow",
);
# perldata中有标量、数组和哈希更详细的介绍。 (perldoc perldata).
# 可以用引用构建更复杂的数据类型,比如嵌套的列表和哈希。
#### 逻辑和循环结构
# Perl有大多数常见的逻辑和循环控制结构
if ( $var ) {
...
} elsif ( $var eq 'bar' ) {
...
} else {
...
}
unless ( condition ) {
...
}
# 上面这个比"if (!condition)"更可读。
# 有Perl特色的后置逻辑结构
print "Yow!" if $zippy;
print "We have no bananas" unless $bananas;
# while
while ( condition ) {
...
}
# for和foreach
for ($i = 0; $i <= $max; $i++) {
...
}
foreach (@array) {
print "This element is $_\n";
}
#### 正则表达式
# Perl对正则表达式有深入广泛的支持,perlrequick和perlretut等文档有详细介绍。简单来说:
# 简单匹配
if (/foo/) { ... } # 如果 $_ 包含"foo"逻辑为真
if ($a =~ /foo/) { ... } # 如果 $a 包含"foo"逻辑为真
# 简单替换
$a =~ s/foo/bar/; # 将$a中的foo替换为bar
$a =~ s/foo/bar/g; # 将$a中所有的foo替换为bar
#### 文件和输入输出
# 可以使用“open()”函数打开文件用于输入输出。
open(my $in, "<", "input.txt") or die "Can't open input.txt: $!";
open(my $out, ">", "output.txt") or die "Can't open output.txt: $!";
open(my $log, ">>", "my.log") or die "Can't open my.log: $!";
# 可以用"<>"操作符读取一个打开的文件句柄。 在标量语境下会读取一行,
# 在列表环境下会将整个文件读入并将每一行赋给列表的一个元素:
my $line = <$in>;
my @lines = <$in>;
#### 子程序
# 写子程序很简单:
sub logger {
my $logmessage = shift;
open my $logfile, ">>", "my.log" or die "Could not open my.log: $!";
print $logfile $logmessage;
}
# 现在可以像内置函数一样调用子程序:
logger("We have a logger subroutine!");
================================================
FILE: learnphp-cn.php
================================================
<?php // PHP必须被包围于 <?php ? > 之中
// 如果你的文件中只有php代码,那么最好省略结束括号标记
// 这是单行注释的标志
# 井号也可以,但是//更常见
/*
这是多行注释
*/
// 使用 "echo" 或者 "print" 来输出信息到标准输出
print('Hello '); // 输出 "Hello " 并且没有换行符
// () 对于echo和print是可选的
echo "World\n"; // 输出 "World" 并且换行
// (每个语句必须以分号结尾)
// 在 <?php 标签之外的语句都被自动输出到标准输出
?>Hello World Again!
<?php
/************************************
* 类型与变量
*/
// 变量以$开始
// 变量可以以字母或者下划线开头,后面可以跟着数字、字母和下划线
// 布尔值是大小写无关的
$boolean = true; // 或 TRUE 或 True
$boolean = false; // 或 FALSE 或 False
// 整型
$int1 = 12; // => 12
$int2 = -12; // => -12
$int3 = 012; // => 10 (0开头代表八进制数)
$int4 = 0x0F; // => 15 (0x开头代表十六进制数)
// 浮点型 (即双精度浮点型)
$float = 1.234;
$float = 1.2e3;
$float = 7E-10;
// 算数运算
$sum = 1 + 1; // 2
$difference = 2 - 1; // 1
$product = 2 * 2; // 4
$quotient = 2 / 1; // 2
// 算数运算的简写
$number = 0;
$number += 1; // $number 自增1
echo $number++; // 输出1 (运算后自增)
echo ++$number; // 输出3 (自增后运算)
$number /= $float; // 先除后赋值给 $number
// 字符串需要被包含在单引号之中
$sgl_quotes = '$String'; // => '$String'
// 如果需要在字符串中引用变量,就需要使用双引号
$dbl_quotes = "This is a $sgl_quotes."; // => 'This is a $String.'
// 特殊字符只有在双引号中有用
$escaped = "This contains a \t tab character.";
$unescaped = 'This just contains a slash and a t: \t';
// 可以把变量包含在一对大括号中
$money = "I have $${number} in the bank.";
// 自 PHP 5.3 开始, nowdocs 可以被用作多行非计算型字符串
$nowdoc = <<<'END'
Multi line
string
END;
// 而Heredocs则可以用作多行计算型字符串
$heredoc = <<<END
Multi line
$sgl_quotes
END;
// 字符串需要用 . 来连接
echo 'This string ' . 'is concatenated';
/********************************
* 数组
*/
// PHP 中的数组都是关联型数组,也就是某些语言中的哈希表或字典
// 在所有PHP版本中均适用:
$associative = array('One' => 1, 'Two' => 2, 'Three' => 3);
// PHP 5.4 中引入了新的语法
$associative = ['One' => 1, 'Two' => 2, 'Three' => 3];
echo $associative['One']; // 输出 1
// 声明为列表实际上是给每个值都分配了一个整数键(key)
$array = ['One', 'Two', 'Three'];
echo $array[0]; // => "One"
/********************************
* 输出
*/
echo('Hello World!');
// 输出到标准输出
// 此时标准输出就是浏览器中的网页
print('Hello World!'); // 和echo相同
// echo和print实际上也属于这个语言本身,所以我们省略括号
echo 'Hello World!';
print 'Hello World!';
$paragraph = 'paragraph';
echo 100; // 直接输出标量
echo $paragraph; // 或者输出变量
// 如果你配置了短标签,或者使用5.4.0及以上的版本
// 你就可以使用简写的echo语法
?>
<p><?= $paragraph ?></p>
<?php
$x = 1;
$y = 2;
$x = $y; // $x 现在和 $y 的值相同
$z = &$y;
// $z 现在持有 $y 的引用. 现在更改 $z 的值也会更改 $y 的值,反之亦然
// 但是改变 $y 的值不会改变 $x 的值
echo $x; // => 2
echo $z; // => 2
$y = 0;
echo $x; // => 2
echo $z; // => 0
/********************************
* 逻辑
*/
$a = 0;
$b = '0';
$c = '1';
$d = '1';
// 如果assert的参数为假,就会抛出警告
// 下面的比较都为真,不管它们的类型是否匹配
assert($a == $b); // 相等
assert($c != $a); // 不等
assert($c <> $a); // 另一种不等的表示
assert($a < $c);
assert($c > $b);
assert($a <= $b);
assert($c >= $d);
// 下面的比较只有在类型相同、值相同的情况下才为真
assert($c === $d);
assert($a !== $d);
assert(1 === '1');
assert(1 !== '1');
// 变量可以根据其使用来进行类型转换
$integer = 1;
echo $integer + $integer; // => 2
$string = '1';
echo $string + $string; // => 2 (字符串在此时被转化为整数)
$string = 'one';
echo $string + $string; // => 0
// 输出0,因为'one'这个字符串无法被转换为整数
// 类型转换可以将一个类型视作另一种类型
$boolean = (boolean) 1; // => true
$zero = 0;
$boolean = (boolean) $zero; // => false
// 还有一些专用的函数来进行类型转换
$integer = 5;
$string = strval($integer);
$var = null; // 空值
/********************************
* 控制结构
*/
if (true) {
print 'I get printed';
}
if (false) {
print 'I don\'t';
} else {
print 'I get printed';
}
if (false) {
print 'Does not get printed';
} elseif(true) {
print 'Does';
}
// 三目运算符
print (false ? 'Does not get printed' : 'Does');
$x = 0;
if ($x === '0') {
print 'Does not print';
} elseif($x == '1') {
print 'Does not print';
} else {
print 'Does print';
}
// 下面的语法常用于模板中:
?>
<?php if ($x): ?>
This is displayed if the test is truthy.
<?php else: ?>
This is displayed otherwise.
<?php endif; ?>
<?php
// 用switch来实现相同的逻辑
switch ($x) {
case '0':
print 'Switch does type coercion';
break; // 在case中必须使用一个break语句,
// 否则在执行完这个语句后会直接执行后面的语句
case 'two':
case 'three':
// 如果$variable是 'two' 或 'three',执行这里的语句
break;
default:
// 其他情况
}
// While, do...while 和 for 循环
$i = 0;
while ($i < 5) {
echo $i++;
}; // 输出 "01234"
echo "\n";
$i = 0;
do {
echo $i++;
} while ($i < 5); // 输出 "01234"
echo "\n";
for ($x = 0; $x < 10; $x++) {
echo $x;
} // 输出 "0123456789"
echo "\n";
$wheels = ['bicycle' => 2, 'car' => 4];
// Foreach 循环可以遍历数组
foreach ($wheels as $wheel_count) {
echo $wheel_count;
} // 输出 "24"
echo "\n";
// 也可以同时遍历键和值
foreach ($wheels as $vehicle => $wheel_count) {
echo "A $vehicle has $wheel_count wheels";
}
echo "\n";
$i = 0;
while ($i < 5) {
if ($i === 3) {
break; // 退出循环
}
echo $i++;
} // 输出 "012"
for ($i = 0; $i < 5; $i++) {
if ($i === 3) {
continue; // 跳过此次遍历
}
echo $i;
} // 输出 "0124"
/********************************
* 函数
*/
// 通过"function"定义函数:
function my_function () {
return 'Hello';
}
echo my_function(); // => "Hello"
// 函数名需要以字母或者下划线开头,
// 后面可以跟着任意的字母、下划线、数字.
function add ($x, $y = 1) { // $y 是可选参数,默认值为 1
$result = $x + $y;
return $result;
}
echo add(4); // => 5
echo add(4, 2); // => 6
// $result 在函数外部不可访问
// print $result; // 抛出警告
// 从 PHP 5.3 起我们可以定义匿名函数
$inc = function ($x) {
return $x + 1;
};
echo $inc(2); // => 3
function foo ($x, $y, $z) {
echo "$x - $y - $z";
}
// 函数也可以返回一个函数
function bar ($x, $y) {
// 用 'use' 将外部的参数引入到里面
return function ($z) use ($x, $y) {
foo($x, $y, $z);
};
}
$bar = bar('A', 'B');
$bar('C'); // 输出 "A - B - C"
// 你也可以通过字符串调用函数
$function_name = 'add';
echo $function_name(1, 2); // => 3
// 在通过程序来决定调用哪个函数时很有用
// 或者,使用 call_user_func(callable $callback [, $parameter [, ... ]]);
/********************************
* 导入
*/
<?php
// 被导入的php文件也必须以php开标签开始
include 'my-file.php';
// 现在my-file.php就在当前作用域中可见了
// 如果这个文件无法被导入(比如文件不存在),会抛出警告
include_once 'my-file.php';
// my-file.php中的代码在其他地方被导入了,那么就不会被再次导入
// 这会避免类的多重定义错误
require 'my-file.php';
require_once 'my-file.php';
// 和include功能相同,只不过如果不能被导入时,会抛出错误
// my-include.php的内容:
<?php
return 'Anything you like.';
// 文件结束
// Include和Require函数也有返回值
$value = include 'my-include.php';
// 被引入的文件是根据文件路径或者include_path配置来查找到的
// 如果文件最终没有被找到,那么就会查找当前文件夹。之后才会报错
/* */
/********************************
* 类
*/
// 类是由class关键字定义的
class MyClass
{
const MY_CONST = 'value'; // 常量
static $staticVar = 'static';
// 属性必须声明其作用域
public $property = 'public';
public $instanceProp;
protected $prot = 'protected'; // 当前类和子类可访问
private $priv = 'private'; // 仅当前类可访问
// 通过 __construct 来定义构造函数
public function __construct($instanceProp) {
// 通过 $this 访问当前对象
$this->instanceProp = $instanceProp;
}
// 方法就是类中定义的函数
public function myMethod()
{
print 'MyClass';
}
final function youCannotOverrideMe()
{
}
public static function myStaticMethod()
{
print 'I am static';
}
}
echo MyClass::MY_CONST; // 输出 'value';
echo MyClass::$staticVar; // 输出 'static';
MyClass::myStaticMethod(); // 输出 'I am static';
// 通过new来新建实例
$my_class = new MyClass('An instance property');
// 如果不传递参数,那么括号可以省略
// 用 -> 来访问成员
echo $my_class->property; // => "public"
echo $my_class->instanceProp; // => "An instance property"
$my_class->myMethod(); // => "MyClass"
// 使用extends来生成子类
class MyOtherClass extends MyClass
{
function printProtectedProperty()
{
echo $this->prot;
}
// 方法覆盖
function myMethod()
{
parent::myMethod();
print ' > MyOtherClass';
}
}
$my_other_class = new MyOtherClass('Instance prop');
$my_other_class->printProtectedProperty(); // => 输出 "protected"
$my_other_class->myMethod(); // 输出 "MyClass > MyOtherClass"
final class YouCannotExtendMe
{
}
// 你可以使用“魔法方法”来生成getter和setter方法
class MyMapClass
{
private $property;
public function __get($key)
{
return $this->$key;
}
public function __set($key, $value)
{
$this->$key = $value;
}
}
$x = new MyMapClass();
echo $x->property; // 会使用 __get() 方法
$x->property = 'Something'; // 会使用 __set() 方法
// 类可以是被定义成抽象类 (使用 abstract 关键字) 或者
// 去实现接口 (使用 implements 关键字).
// 接口需要通过interface关键字来定义
interface InterfaceOne
{
public function doSomething();
}
interface InterfaceTwo
{
public function doSomethingElse();
}
// 接口可以被扩展
interface InterfaceThree extends InterfaceTwo
{
public function doAnotherContract();
}
abstract class MyAbstractClass implements InterfaceOne
{
public $x = 'doSomething';
}
class MyConcreteClass extends MyAbstractClass implements InterfaceTwo
{
public function doSomething()
{
echo $x;
}
public function doSomethingElse()
{
echo 'doSomethingElse';
}
}
// 一个类可以实现多个接口
class SomeOtherClass implements InterfaceOne, InterfaceTwo
{
public function doSomething()
{
echo 'doSomething';
}
public function doSomethingElse()
{
echo 'doSomethingElse';
}
}
/********************************
* 特征
*/
// 特征 从 PHP 5.4.0 开始包括,需要用 "trait" 这个关键字声明
trait MyTrait
{
public function myTraitMethod()
{
print 'I have MyTrait';
}
}
class MyTraitfulClass
{
use MyTrait;
}
$cls = new MyTraitfulClass();
$cls->myTraitMethod(); // 输出 "I have MyTrait"
/********************************
* 命名空间
*/
// 这部分是独立于这个文件的
// 因为命名空间必须在一个文件的开始处。
<?php
// 类会被默认的放在全局命名空间中,可以被一个\来显式调用
$cls = new \MyClass();
// 为一个文件设置一个命名空间
namespace My\Namespace;
class MyClass
{
}
// (或者从其他文件中)
$cls = new My\Namespace\MyClass;
//或者从其他命名空间中
namespace My\Other\Namespace;
use My\Namespace\MyClass;
$cls = new MyClass();
// 你也可以为命名空间起一个别名
namespace My\Other\Namespace;
use My\Namespace as SomeOtherNamespace;
$cls = new SomeOtherNamespace\MyClass();
*/
================================================
FILE: learnpython-cn.py
================================================
# 单行注释
""" 多行字符串可以用
三个引号包裹,不过这也可以被当做
多行注释
"""
####################################################
## 1. 原始数据类型和操作符
####################################################
# 数字类型
3 # => 3
# 简单的算数
1 + 1 # => 2
8 - 1 # => 7
10 * 2 # => 20
35 / 5 # => 7
# 整数的除法会自动取整
5 / 2 # => 2
# 要做精确的除法,我们需要引入浮点数
2.0 # 浮点数
11.0 / 4.0 # => 2.75 精确多了
# 括号具有最高优先级
(1 + 3) * 2 # => 8
# 布尔值也是基本的数据类型
True
False
# 用 not 来取非
not True # => False
not False # => True
# 相等
1 == 1 # => True
2 == 1 # => False
# 不等
1 != 1 # => False
2 != 1 # => True
# 更多的比较操作符
1 < 10 # => True
1 > 10 # => False
2 <= 2 # => True
2 >= 2 # => True
# 比较运算可以连起来写!
1 < 2 < 3 # => True
2 < 3 < 2 # => False
# 字符串通过 " 或 ' 括起来
"This is a string."
'This is also a string.'
# 字符串通过加号拼接
"Hello " + "world!" # => "Hello world!"
# 字符串可以被视为字符的列表
"This is a string"[0] # => 'T'
# % 可以用来格式化字符串
"%s can be %s" % ("strings", "interpolated")
# 也可以用 format 方法来格式化字符串
# 推荐使用这个方法
"{0} can be {1}".format("strings", "formatted")
# 也可以用变量名代替数字
"{name} wants to eat {food}".format(name="Bob", food="lasagna")
# None 是对象
None # => None
# 不要用相等 `==` 符号来和None进行比较
# 要用 `is`
"etc" is None # => False
None is None # => True
# 'is' 可以用来比较对象的相等性
# 这个操作符在比较原始数据时没多少用,但是比较对象时必不可少
# None, 0, 和空字符串都被算作 False
# 其他的均为 True
0 == False # => True
"" == False # => True
####################################################
## 2. 变量和集合
####################################################
# 很方便的输出
print "I'm Python. Nice to meet you!"
# 给变量赋值前不需要事先声明
some_var = 5 # 一般建议使用小写字母和下划线组合来做为变量名
some_var # => 5
# 访问未赋值的变量会抛出异常
# 可以查看控制流程一节来了解如何异常处理
some_other_var # 抛出 NameError
# if 语句可以作为表达式来使用
"yahoo!" if 3 > 2 else 2 # => "yahoo!"
# 列表用来保存序列
li = []
# 可以直接初始化列表
other_li = [4, 5, 6]
# 在列表末尾添加元素
li.append(1) # li 现在是 [1]
li.append(2) # li 现在是 [1, 2]
li.append(4) # li 现在是 [1, 2, 4]
li.append(3) # li 现在是 [1, 2, 4, 3]
# 移除列表末尾元素
li.pop() # => 3 li 现在是 [1, 2, 4]
# 重新加进去
li.append(3) # li is now [1, 2, 4, 3] again.
# 像其他语言访问数组一样访问列表
li[0] # => 1
# 访问最后一个元素
li[-1] # => 3
# 越界会抛出异常
li[4] # 抛出越界异常
# 切片语法需要用到列表的索引访问
# 可以看做数学之中左闭右开区间
li[1:3] # => [2, 4]
# 省略开头的元素
li[2:] # => [4, 3]
# 省略末尾的元素
li[:3] # => [1, 2, 4]
# 删除特定元素
del li[2] # li 现在是 [1, 2, 3]
# 合并列表
li + other_li # => [1, 2, 3, 4, 5, 6] - 并不会不改变这两个列表
# 通过拼接来合并列表
li.extend(other_li) # li 是 [1, 2, 3, 4, 5, 6]
# 用 in 来返回元素是否在列表中
1 in li # => True
# 返回列表长度
len(li) # => 6
# 元组类似于列表,但它是不可改变的
tup = (1, 2, 3)
tup[0] # => 1
tup[0] = 3 # 类型错误
# 对于大多数的列表操作,也适用于元组
len(tup) # => 3
tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6)
tup[:2] # => (1, 2)
2 in tup # => True
# 你可以将元组解包赋给多个变量
a, b, c = (1, 2, 3) # a 是 1,b 是 2,c 是 3
# 如果不加括号,将会被自动视为元组
d, e, f = 4, 5, 6
# 现在我们可以看看交换两个数字是多么容易的事
e, d = d, e # d 是 5,e 是 4
# 字典用来储存映射关系
empty_dict = {}
# 字典初始化
filled_dict = {"one": 1, "two": 2, "three": 3}
# 字典也用中括号访问元素
filled_dict["one"] # => 1
# 把所有的键保存在列表中
filled_dict.keys() # => ["three", "two", "one"]
# 键的顺序并不是唯一的,得到的不一定是这个顺序
# 把所有的值保存在列表中
filled_dict.values() # => [3, 2, 1]
# 和键的顺序相同
# 判断一个键是否存在
"one" in filled_dict # => True
1 in filled_dict # => False
# 查询一个不存在的键会抛出 KeyError
filled_dict["four"] # KeyError
# 用 get 方法来避免 KeyError
filled_dict.get("one") # => 1
filled_dict.get("four") # => None
# get 方法支持在不存在的时候返回一个默认值
filled_dict.get("one", 4) # => 1
filled_dict.get("four", 4) # => 4
# setdefault 是一个更安全的添加字典元素的方法
filled_dict.setdefault("five", 5) # filled_dict["five"] 的值为 5
filled_dict.setdefault("five", 6) # filled_dict["five"] 的值仍然是 5
# 集合储存无顺序的元素
empty_set = set()
# 初始化一个集合
some_set = set([1, 2, 2, 3, 4]) # some_set 现在是 set([1, 2, 3, 4])
# Python 2.7 之后,大括号可以用来表示集合
filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4}
# 向集合添加元素
filled_set.add(5) # filled_set 现在是 {1, 2, 3, 4, 5}
# 用 & 来计算集合的交
other_set = {3, 4, 5, 6}
filled_set & other_set # => {3, 4, 5}
# 用 | 来计算集合的并
filled_set | other_set # => {1, 2, 3, 4, 5, 6}
# 用 - 来计算集合的差
{1, 2, 3, 4} - {2, 3, 5} # => {1, 4}
# 用 in 来判断元素是否存在于集合中
2 in filled_set # => True
10 in filled_set # => False
####################################################
## 3. 控制流程
####################################################
# 新建一个变量
some_var = 5
# 这是个 if 语句,在 python 中缩进是很重要的。
# 下面的代码片段将会输出 "some var is smaller than 10"
if some_var > 10:
print "some_var is totally bigger than 10."
elif some_var < 10: # 这个 elif 语句是不必须的
print "some_var is smaller than 10."
else: # 这个 else 也不是必须的
print "some_var is indeed 10."
"""
用for循环遍历列表
输出:
dog is a mammal
cat is a mammal
mouse is a mammal
"""
for animal in ["dog", "cat", "mouse"]:
# 你可以用 % 来格式化字符串
print "%s is a mammal" % animal
"""
`range(number)` 返回从0到给定数字的列表
输出:
0
1
2
3
"""
for i in range(4):
print i
"""
while 循环
输出:
0
1
2
3
"""
x = 0
while x < 4:
print x
x += 1 # x = x + 1 的简写
# 用 try/except 块来处理异常
# Python 2.6 及以上适用:
try:
# 用 raise 来抛出异常
raise IndexError("This is an index error")
except IndexError as e:
pass # pass 就是什么都不做,不过通常这里会做一些恢复工作
####################################################
## 4. 函数
####################################################
# 用 def 来新建函数
def add(x, y):
print "x is %s and y is %s" % (x, y)
return x + y # 通过 return 来返回值
# 调用带参数的函数
add(5, 6) # => 输出 "x is 5 and y is 6" 返回 11
# 通过关键字赋值来调用函数
add(y=6, x=5) # 顺序是无所谓的
# 我们也可以定义接受多个变量的函数,这些变量是按照顺序排列的
def varargs(*args):
return args
varargs(1, 2, 3) # => (1,2,3)
# 我们也可以定义接受多个变量的函数,这些变量是按照关键字排列的
def keyword_args(**kwargs):
return kwargs
# 实际效果:
keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"}
# 你也可以同时将一个函数定义成两种形式
def all_the_args(*args, **kwargs):
print args
print kwargs
"""
all_the_args(1, 2, a=3, b=4) prints:
(1, 2)
{"a": 3, "b": 4}
"""
# 当调用函数的时候,我们也可以进行相反的操作,把元组和字典展开为参数
args = (1, 2, 3, 4)
kwargs = {"a": 3, "b": 4}
all_the_args(*args) # 等价于 foo(1, 2, 3, 4)
all_the_args(**kwargs) # 等价于 foo(a=3, b=4)
all_the_args(*args, **kwargs) # 等价于 foo(1, 2, 3, 4, a=3, b=4)
# 函数在 python 中是一等公民
def create_adder(x):
def adder(y):
return x + y
return adder
add_10 = create_adder(10)
add_10(3) # => 13
# 匿名函数
(lambda x: x > 2)(3) # => True
# 内置高阶函数
map(add_10, [1, 2, 3]) # => [11, 12, 13]
filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7]
# 可以用列表方法来对高阶函数进行更巧妙的引用
[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]
####################################################
## 5. 类
####################################################
# 我们新建的类是从 object 类中继承的
class Human(object):
# 类属性,由所有类的对象共享
species = "H. sapiens"
# 基本构造函数
def __init__(self, name):
# 将参数赋给对象成员属性
self.name = name
# 成员方法,参数要有 self
def say(self, msg):
return "%s: %s" % (self.name, msg)
# 类方法由所有类的对象共享
# 这类方法在调用时,会把类本身传给第一个参数
@classmethod
def get_species(cls):
return cls.species
# 静态方法是不需要类和对象的引用就可以调用的方法
@staticmethod
def grunt():
return "*grunt*"
# 实例化一个类
i = Human(name="Ian")
print i.say("hi") # 输出 "Ian: hi"
j = Human("Joel")
print j.say("hello") # 输出 "Joel: hello"
# 访问类的方法
i.get_species() # => "H. sapiens"
# 改变共享属性
Human.species = "H. neanderthalensis"
i.get_species() # => "H. neanderthalensis"
j.get_species() # => "H. neanderthalensis"
# 访问静态变量
Human.grunt() # => "*grunt*"
####################################################
## 6. 模块
####################################################
# 我们可以导入其他模块
import math
print math.sqrt(16) # => 4
# 我们也可以从一个模块中导入特定的函数
from math import ceil, floor
print ceil(3.7) # => 4.0
print floor(3.7) # => 3.0
# 从模块中导入所有的函数
# 警告:不推荐使用
from math import *
# 简写模块名
import math as m
math.sqrt(16) == m.sqrt(16) # => True
# Python的模块其实只是普通的python文件
# 你也可以创建自己的模块,并且导入它们
# 模块的名字就和文件的名字相同
# 也可以通过下面的方法查看模块中有什么属性和方法
import math
dir(math)
================================================
FILE: learnpython3-cn.py
================================================
# 用井字符开头的是单行注释
""" 多行字符串用三个引号
包裹,也常被用来做多
行注释
"""
####################################################
## 1. 原始数据类型和运算符
####################################################
# 整数
3 # => 3
# 算术没有什么出乎意料的
1 + 1 # => 2
8 - 1 # => 7
10 * 2 # => 20
# 但是除法例外,会自动转换成浮点数
35 / 5 # => 7.0
5 / 3 # => 1.6666666666666667
# 整数除法的结果都是向下取整
5 // 3 # => 1
5.0 // 3.0 # => 1.0 # 浮点数也可以
-5 // 3 # => -2
-5.0 // 3.0 # => -2.0
# 浮点数的运算结果也是浮点数
3 * 2.0 # => 6.0
# 模除
7 % 3 # => 1
# x的y次方
2**4 # => 16
# 用括号决定优先级
(1 + 3) * 2 # => 8
# 布尔值
True
False
# 用not取非
not True # => False
not False # => True
# 逻辑运算符,注意and和or都是小写
True and False #=> False
False or True #=> True
# 整数也可以当作布尔值
0 and 2 #=> 0
-5 or 0 #=> -5
0 == False #=> True
2 == True #=> False
1 == True #=> True
# 用==判断相等
1 == 1 # => True
2 == 1 # => False
# 用!=判断不等
1 != 1 # => False
2 != 1 # => True
# 比较大小
1 < 10 # => True
1 > 10 # => False
2 <= 2 # => True
2 >= 2 # => True
# 大小比较可以连起来!
1 < 2 < 3 # => True
2 < 3 < 2 # => False
# 字符串用单引双引都可以
"这是个字符串"
'这也是个字符串'
# 用加号连接字符串
"Hello " + "world!" # => "Hello world!"
# 字符串可以被当作字符列表
"This is a string"[0] # => 'T'
# 用.format来格式化字符串
"{} can be {}".format("strings", "interpolated")
# 可以重复参数以节省时间
"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick")
#=> "Jack be nimble, Jack be quick, Jack jump over the candle stick"
# 如果不想数参数,可以用关键字
"{name} wants to eat {food}".format(name="Bob", food="lasagna") #=> "Bob wants to eat lasagna"
# 如果你的Python3程序也要在Python2.5以下环境运行,也可以用老式的格式化语法
"%s can be %s the %s way" % ("strings", "interpolated", "old")
# None是一个对象
None # => None
# 当与None进行比较时不要用 ==,要用is。is是用来比较两个变量是否指向同一个对象。
"etc" is None # => False
None is None # => True
# None,0,空字符串,空列表,空字典都算是False
# 所有其他值都是True
bool(0) # => False
bool("") # => False
bool([]) #=> False
bool({}) #=> False
####################################################
## 2. 变量和集合
####################################################
# print是内置的打印函数
print("I'm Python. Nice to meet you!")
# 在给变量赋值前不用提前声明
# 传统的变量命名是小写,用下划线分隔单词
some_var = 5
some_var # => 5
# 访问未赋值的变量会抛出异常
# 参考流程控制一段来学习异常处理
some_unknown_var # 抛出NameError
# 用列表(list)储存序列
li = []
# 创建列表时也可以同时赋给元素
other_li = [4, 5, 6]
# 用append在列表最后追加元素
li.append(1) # li现在是[1]
li.append(2) # li现在是[1, 2]
li.append(4) # li现在是[1, 2, 4]
li.append(3) # li现在是[1, 2, 4, 3]
# 用pop从列表尾部删除
li.pop() # => 3 且li现在是[1, 2, 4]
# 把3再放回去
li.append(3) # li变回[1, 2, 4, 3]
# 列表存取跟数组一样
li[0] # => 1
# 取出最后一个元素
li[-1] # => 3
# 越界存取会造成IndexError
li[4] # 抛出IndexError
# 列表有切割语法
li[1:3] # => [2, 4]
# 取尾
li[2:] # => [4, 3]
# 取头
li[:3] # => [1, 2, 4]
# 隔一个取一个
li[::2] # =>[1, 4]
# 倒排列表
li[::-1] # => [3, 4, 2, 1]
# 可以用三个参数的任何组合来构建切割
# li[始:终:步伐]
# 用del删除任何一个元素
del li[2] # li is now [1, 2, 3]
# 列表可以相加
# 注意:li和other_li的值都不变
li + other_li # => [1, 2, 3, 4, 5, 6]
# 用extend拼接列表
li.extend(other_li) # li现在是[1, 2, 3, 4, 5, 6]
# 用in测试列表是否包含值
1 in li # => True
# 用len取列表长度
len(li) # => 6
# 元组是不可改变的序列
tup = (1, 2, 3)
tup[0] # => 1
tup[0] = 3 # 抛出TypeError
# 列表允许的操作元组大都可以
len(tup) # => 3
tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6)
tup[:2] # => (1, 2)
2 in tup # => True
# 可以把元组合列表解包,赋值给变量
a, b, c = (1, 2, 3) # 现在a是1,b是2,c是3
# 元组周围的括号是可以省略的
d, e, f = 4, 5, 6
# 交换两个变量的值就这么简单
e, d = d, e # 现在d是5,e是4
# 用字典表达映射关系
empty_dict = {}
# 初始化的字典
filled_dict = {"one": 1, "two": 2, "three": 3}
# 用[]取值
filled_dict["one"] # => 1
# 用keys获得所有的键。因为keys返回一个可迭代对象,所以在这里把结果包在list里。我们下面会详细介绍可迭代。
# 注意:字典键的顺序是不定的,你得到的结果可能和以下不同。
list(filled_dict.keys()) # => ["three", "two", "one"]
# 用values获得所有的值。跟keys一样,要用list包起来,顺序也可能不同。
list(filled_dict.values()) # => [3, 2, 1]
# 用in测试一个字典是否包含一个键
"one" in filled_dict # => True
1 in filled_dict # => False
# 访问不存在的键会导致KeyError
filled_dict["four"] # KeyError
# 用get来避免KeyError
filled_dict.get("one") # => 1
filled_dict.get("four") # => None
# 当键不存在的时候get方法可以返回默认值
filled_dict.get("one", 4) # => 1
filled_dict.get("four", 4) # => 4
# setdefault方法只有当键不存在的时候插入新值
filled_dict.setdefault("five", 5) # filled_dict["five"]设为5
filled_dict.setdefault("five", 6) # filled_dict["five"]还是5
# 字典赋值
filled_dict.update({"four":4}) #=> {"one": 1, "two": 2, "three": 3, "four": 4}
filled_dict["four"] = 4 # 另一种赋值方法
# 用del删除
del filled_dict["one"] # 从filled_dict中把one删除
# 用set表达集合
empty_set = set()
# 初始化一个集合,语法跟字典相似。
some_set = {1, 1, 2, 2, 3, 4} # some_set现在是{1, 2, 3, 4}
# 可以把集合赋值于变量
filled_set = some_set
# 为集合添加元素
filled_set.add(5) # filled_set现在是{1, 2, 3, 4, 5}
# & 取交集
other_set = {3, 4, 5, 6}
filled_set & other_set # => {3, 4, 5}
# | 取并集
filled_set | other_set # => {1, 2, 3, 4, 5, 6}
# - 取补集
{1, 2, 3, 4} - {2, 3, 5} # => {1, 4}
# in 测试集合是否包含元素
2 in filled_set # => True
10 in filled_set # => False
####################################################
## 3. 流程控制和迭代器
####################################################
# 先随便定义一个变量
some_var = 5
# 这是个if语句。注意缩进在Python里是有意义的
# 印出"some_var比10小"
if some_var > 10:
print("some_var比10大")
elif some_var < 10: # elif句是可选的
print("some_var比10小")
else: # else也是可选的
print("some_var就是10")
"""
用for循环语句遍历列表
打印:
dog is a mammal
cat is a mammal
mouse is a mammal
"""
for animal in ["dog", "cat", "mouse"]:
print("{} is a mammal".format(animal))
"""
"range(number)"返回数字列表从0到给的数字
打印:
0
1
2
3
"""
for i in range(4):
print(i)
"""
while循环直到条件不满足
打印:
0
1
2
3
"""
x = 0
while x < 4:
print(x)
x += 1 # x = x + 1 的简写
# 用try/except块处理异常状况
try:
# 用raise抛出异常
raise IndexError("This is an index error")
except IndexError as e:
pass # pass是无操作,但是应该在这里处理错误
except (TypeError, NameError):
pass # 可以同时处理不同类的错误
else: # else语句是可选的,必须在所有的except之后
print("All good!") # 只有当try运行完没有错误的时候这句才会运行
# Python提供一个叫做可迭代(iterable)的基本抽象。一个可迭代对象是可以被当作序列
# 的对象。比如说上面range返回的对象就是可迭代的。
filled_dict = {"one": 1, "two": 2, "three": 3}
our_iterable = filled_dict.keys()
print(our_iterable) # => range(1,10) 是一个实现可迭代接口的对象
# 可迭代对象可以遍历
for i in our_iterable:
print(i) # 打印 one, two, three
# 但是不可以随机访问
our_iterable[1] # 抛出TypeError
# 可迭代对象知道怎么生成迭代器
our_iterator = iter(our_iterable)
# 迭代器是一个可以记住遍历的位置的对象
# 用__next__可以取得下一个元素
our_iterator.__next__() #=> "one"
# 再一次调取__next__时会记得位置
our_iterator.__next__() #=> "two"
our_iterator.__next__() #=> "three"
# 当迭代器所有元素都取出后,会抛出StopIteration
our_iterator.__next__() # 抛出StopIteration
# 可以用list一次取出迭代器所有的元素
list(filled_dict.keys()) #=> Returns ["one", "two", "three"]
####################################################
## 4. 函数
####################################################
# 用def定义新函数
def add(x, y):
print("x is {} and y is {}".format(x, y))
return x + y # 用return语句返回
# 调用函数
add(5, 6) # => 印出"x is 5 and y is 6"并且返回11
# 也可以用关键字参数来调用函数
add(y=6, x=5) # 关键字参数可以用任何顺序
# 我们可以定义一个可变参数函数
def varargs(*args):
return args
varargs(1, 2, 3) # => (1, 2, 3)
# 我们也可以定义一个关键字可变参数函数
def keyword_args(**kwargs):
return kwargs
# 我们来看看结果是什么:
keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"}
# 这两种可变参数可以混着用
def all_the_args(*args, **kwargs):
print(args)
print(kwargs)
"""
all_the_args(1, 2, a=3, b=4) prints:
(1, 2)
{"a": 3, "b": 4}
"""
# 调用可变参数函数时可以做跟上面相反的,用*展开序列,用**展开字典。
args = (1, 2, 3, 4)
kwargs = {"a": 3, "b": 4}
all_the_args(*args) # 相当于 foo(1, 2, 3, 4)
all_the_args(**kwargs) # 相当于 foo(a=3, b=4)
all_the_args(*args, **kwargs) # 相当于 foo(1, 2, 3, 4, a=3, b=4)
# 函数作用域
x = 5
def setX(num):
# 局部作用域的x和全局域的x是不同的
x = num # => 43
print (x) # => 43
def setGlobalX(num):
global x
print (x) # => 5
x = num # 现在全局域的x被赋值
print (x) # => 6
setX(43)
setGlobalX(6)
# 函数在Python是一等公民
def create_adder(x):
def adder(y):
return x + y
return adder
add_10 = create_adder(10)
add_10(3) # => 13
# 也有匿名函数
(lambda x: x > 2)(3) # => True
# 内置的高阶函数
map(add_10, [1, 2, 3]) # => [11, 12, 13]
filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7]
# 用列表推导式可以简化映射和过滤。列表推导式的返回值是另一个列表。
[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]
####################################################
## 5. 类
####################################################
# 定义一个继承object的类
class Human(object):
# 类属性,被所有此类的实例共用。
species = "H. sapiens"
# 构造方法,当实例被初始化时被调用。注意名字前后的双下划线,这是表明这个属
# 性或方法对Python有特殊意义,但是允许用户自行定义。你自己取名时不应该用这
# 种格式。
def __init__(self, name):
# Assign the argument to the instance's name attribute
self.name = name
# 实例方法,第一个参数总是self,就是这个实例对象
def say(self, msg):
return "{name}: {message}".format(name=self.name, message=msg)
# 类方法,被所有此类的实例共用。第一个参数是这个类对象。
@classmethod
def get_species(cls):
return cls.species
# 静态方法。调用时没有实例或类的绑定。
@staticmethod
def grunt():
return "*grunt*"
# 构造一个实例
i = Human(name="Ian")
print(i.say("hi")) # 印出 "Ian: hi"
j = Human("Joel")
print(j.say("hello")) # 印出 "Joel: hello"
# 调用一个类方法
i.get_species() # => "H. sapiens"
# 改一个共用的类属性
Human.species = "H. neanderthalensis"
i.get_species() # => "H. neanderthalensis"
j.get_species() # => "H. neanderthalensis"
# 调用静态方法
Human.grunt() # => "*grunt*"
####################################################
## 6. 模块
####################################################
# 用import导入模块
import math
print(math.sqrt(16)) # => 4
# 也可以从模块中导入个别值
from math import ceil, floor
print(ceil(3.7)) # => 4.0
print(floor(3.7)) # => 3.0
# 可以导入一个模块中所有值
# 警告:不建议这么做
from math import *
# 如此缩写模块名字
import math as m
math.sqrt(16) == m.sqrt(16) # => True
# Python模块其实就是普通的Python文件。你可以自己写,然后导入,
# 模块的名字就是文件的名字。
# 你可以这样列出一个模块里所有的值
import math
dir(math)
####################################################
## 7. 高级用法
####################################################
# 用生成器(generators)方便地写惰性运算
def double_numbers(iterable):
for i in iterable:
yield i + i
# 生成器只有在需要时才计算下一个值。它们每一次循环只生成一个值,而不是把所有的
# 值全部算好。这意味着double_numbers不会生成大于15的数字。
#
# range的返回值也是一个生成器,不然一个1到900000000的列表会花很多时间和内存。
#
# 如果你想用一个Python的关键字当作变量名,可以加一个下划线来区分。
range_ = range(1, 900000000)
# 当找到一个 >=30 的结果就会停
for i in double_numbers(range_):
print(i)
if i >= 30:
break
# 装饰器(decorators)
# 这个例子中,beg装饰say
# beg会先调用say。如果返回的say_please为真,beg会改变返回的字符串。
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, "Please! I am poor :(")
return msg
return wrapper
@beg
def say(say_please=False):
msg = "Can you buy me a beer?"
return msg, say_please
print(say()) # Can you buy me a beer?
print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
================================================
FILE: learnr-cn.r
================================================
# 评论以 # 开始
# R 语言原生不支持 多行注释
# 但是你可以像这样来多行注释
# 在窗口里按回车键可以执行一条命令
###################################################################
# 不用懂编程就可以开始动手了
###################################################################
data() # 浏览内建的数据集
data(rivers) # 北美主要河流的长度(数据集)
ls() # 在工作空间中查看「河流」是否出现
head(rivers) # 撇一眼数据集
# 735 320 325 392 524 450
length(rivers) # 我们测量了多少条河流?
# 141
summary(rivers)
# Min. 1st Qu. Median Mean 3rd Qu. Max.
# 135.0 310.0 425.0 591.2 680.0 3710.0
stem(rivers) # 茎叶图(一种类似于直方图的展现形式)
#
# The decimal point is 2 digit(s) to the right of the |
#
# 0 | 4
# 2 | 011223334555566667778888899900001111223333344455555666688888999
# 4 | 111222333445566779001233344567
# 6 | 000112233578012234468
# 8 | 045790018
# 10 | 04507
# 12 | 1471
# 14 | 56
# 16 | 7
# 18 | 9
# 20 |
# 22 | 25
# 24 | 3
# 26 |
# 28 |
# 30 |
# 32 |
# 34 |
# 36 | 1
stem(log(rivers)) # 查看数据集的方式既不是标准形式,也不是取log后的结果! 看起来,是钟形曲线形式的基本数据集
# The decimal point is 1 digit(s) to the left of the |
#
# 48 | 1
# 50 |
# 52 | 15578
# 54 | 44571222466689
# 56 | 023334677000124455789
# 58 | 00122366666999933445777
# 60 | 122445567800133459
# 62 | 112666799035
# 64 | 00011334581257889
# 66 | 003683579
# 68 | 0019156
# 70 | 079357
# 72 | 89
# 74 | 84
# 76 | 56
# 78 | 4
# 80 |
# 82 | 2
hist(rivers, col="#333333", border="white", breaks=25) # 试试用这些参数画画 (译者注:给 river 做统计频数直方图,包含了这些参数:数据源,颜色,边框,空格)
hist(log(rivers), col="#333333", border="white", breaks=25) #你还可以做更多式样的绘图
# 还有其他一些简单的数据集可以被用来加载。R 语言包括了大量这种 data()
data(discoveries)
plot(discoveries, col="#333333", lwd=3, xlab="Year", main="Number of important discoveries per year")
# 译者注:参数为(数据源,颜色,线条宽度,X 轴名称,标题)
plot(discoveries, col="#333333", lwd=3, type = "h", xlab="Year", main="Number of important discoveries per year")
# 除了按照默认的年份排序,我们还可以排序来发现特征
sort(discoveries)
# [1] 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2
# [26] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3
# [51] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4
# [76] 4 4 4 4 5 5 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 8 9 10 12
stem(discoveries, scale=2) # 译者注:茎叶图(数据,放大系数)
#
# The decimal point is at the |
#
# 0 | 000000000
# 1 | 000000000000
# 2 | 00000000000000000000000000
# 3 | 00000000000000000000
# 4 | 000000000000
# 5 | 0000000
# 6 | 000000
# 7 | 0000
# 8 | 0
# 9 | 0
# 10 | 0
# 11 |
# 12 | 0
max(discoveries)
# 12
summary(discoveries)
# Min. 1st Qu. Median Mean 3rd Qu. Max.
# 0.0 2.0 3.0 3.1 4.0 12.0
#基本的统计学操作也不需要任何编程知识
#随机生成数据
round(runif(7, min=.5, max=6.5))
# 译者注:runif 产生随机数,round 四舍五入
# 1 4 6 1 4 6 4
# 你输出的结果会和我们给出的不同,除非我们设置了相同的随机种子 random.seed(31337)
#从标准高斯函数中随机生成 9 次
rnorm(9)
# [1] 0.07528471 1.03499859 1.34809556 -0.82356087 0.61638975 -1.88757271
# [7] -0.59975593 0.57629164 1.08455362
#########################
# 基础编程
#########################
# 数值
#“数值”指的是双精度的浮点数
5 # 5
class(5) # "numeric"
5e4 # 50000 # 用科学技术法方便的处理极大值、极小值或者可变的量级
6.02e23 # 阿伏伽德罗常数#
1.6e-35 # 布朗克长度
# 长整数并用 L 结尾
5L # 5
#输出5L
class(5L) # "integer"
# 可以自己试一试?用 class() 函数获取更多信息
# 事实上,你可以找一些文件查阅 `xyz` 以及xyz的差别
# `xyz` 用来查看源码实现,?xyz 用来看帮助
# 算法
10 + 66 # 76
53.2 - 4 # 49.2
2 * 2.0 # 4
3L / 4 # 0.75
3 %% 2 # 1
# 特殊数值类型
class(NaN) # "numeric"
class(Inf) # "numeric"
class(-Inf) # "numeric" # 在以下场景中会用到 integrate( dnorm(x), 3, Inf ) -- 消除 Z 轴数据
# 但要注意,NaN 并不是唯一的特殊数值类型……
class(NA) # 看上面
class(NULL) # NULL
# 简单列表
c(6, 8, 7, 5, 3, 0, 9) # 6 8 7 5 3 0 9
c('alef', 'bet', 'gimmel', 'dalet', 'he')
c('Z', 'o', 'r', 'o') == "Zoro" # FALSE FALSE FALSE FALSE
# 一些优雅的内置功能
5:15 # 5 6 7 8 9 10 11 12 13 14 15
seq(from=0, to=31337, by=1337)
# [1] 0 1337 2674 4011 5348 6685 8022 9359 10696 12033 13370 14707
# [13] 16044 17381 18718 20055 21392 22729 24066 25403 26740 28077 29414 30751
letters
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
# [20] "t" "u" "v" "w" "x" "y" "z"
month.abb # "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"
# Access the n'th element of a list with list.name[n] or sometimes list.name[[n]]
# 使用 list.name[n] 来访问第 n 个列表元素,有时候需要使用 list.name[[n]]
letters[18] # "r"
LETTERS[13] # "M"
month.name[9] # "September"
c(6, 8, 7, 5, 3, 0, 9)[3] # 7
# 字符串
# 字符串和字符在 R 语言中没有区别
"Horatio" # "Horatio"
class("Horatio") # "character"
substr("Fortuna multis dat nimis, nulli satis.", 9, 15) # "multis "
gsub('u', 'ø', "Fortuna multis dat nimis, nulli satis.") # "Fortøna møltis dat nimis, nølli satis."
# 逻辑值
# 布尔值
class(TRUE) # "logical"
class(FALSE) # "logical"
# 和我们预想的一样
TRUE == TRUE # TRUE
TRUE == FALSE # FALSE
FALSE != FALSE # FALSE
FALSE != TRUE # TRUE
# 缺失数据(NA)也是逻辑值
class(NA) # "logical"
#定义NA为逻辑型
# 因子
# 因子是为数据分类排序设计的(像是排序小朋友们的年级或性别)
levels(factor(c("female", "male", "male", "female", "NA", "female"))) # "female" "male" "NA"
factor(c("female", "female", "male", "NA", "female"))
# female female male NA female
# Levels: female male NA
data(infert) # 自然以及引产导致的不育症
levels(infert$education) # "0-5yrs" "6-11yrs" "12+ yrs"
# 变量
# 有许多种方式用来赋值
x = 5 # 这样可以
y <- "1" # 更推荐这样
TRUE -> z # 这样可行,但是很怪
#我们还可以使用强制转型
as.numeric(y) # 1
as.character(x) # "5"
# 循环
# for 循环语句
for (i in 1:4) {
print(i)
}
# while 循环
a <- 10
while (a > 4) {
cat(a, "...", sep = "")
a <- a - 1
}
# 记住,在 R 语言中 for / while 循环都很慢
# 建议使用 apply()(我们一会介绍)来错做一串数据(比如一列或者一行数据)
# IF/ELSE
# 再来看这些优雅的标准
if (4 > 3) {
print("Huzzah! It worked!")
} else {
print("Noooo! This is blatantly illogical!")
}
# =>
# [1] "Huzzah! It worked!"
# 函数
# 定义如下
jiggle <- function(x) {
x + rnorm(x, sd=.1) #add in a bit of (controlled) noise
return(x)
}
# 和其他 R 语言函数一样调用
jiggle(5) # 5±ε. 使用 set.seed(2716057) 后, jiggle(5)==5.005043
#########################
# 数据容器:vectors, matrices, data frames, and arrays
#########################
# 单维度
# 你可以将目前我们学习到的任何类型矢量化,只要它们拥有相同的类型
vec <- c(8, 9, 10, 11)
vec # 8 9 10 11
# 矢量的类型是这一组数据元素的类型
class(vec) # "numeric"
# If you vectorize items of different classes, weird coercions happen
#如果你强制的将不同类型数值矢量化,会出现特殊值
c(TRUE, 4) # 1 4
c("dog", TRUE, 4) # "dog" "TRUE" "4"
#我们这样来取内部数据,(R 的下标索引顺序 1 开始)
vec[1] # 8
# 我们可以根据条件查找特定数据
which(vec %% 2 == 0) # 1 3
# 抓取矢量中第一个和最后一个字符
head(vec, 1) # 8
tail(vec, 1) # 11
#如果下标溢出或不存会得到 NA
vec[6] # NA
# 你可以使用 length() 获取矢量的长度
length(vec) # 4
# 你可以直接操作矢量或者矢量的子集
vec * 4 # 16 20 24 28
vec[2:3] * 5 # 25 30
# 这里有许多内置的函数,来表现向量
mean(vec) # 9.5
var(vec) # 1.666667
sd(vec) # 1.290994
max(vec) # 11
min(vec) # 8
sum(vec) # 38
# 二维(相同元素类型)
#你可以为同样类型的变量建立矩阵
mat <- matrix(nrow = 3, ncol = 2, c(1,2,3,4,5,6))
mat
# =>
# [,1] [,2]
# [1,] 1 4
# [2,] 2 5
# [3,] 3 6
# 和 vector 不一样的是,一个矩阵的类型真的是 「matrix」,而不是内部元素的类型
class(mat) # => "matrix"
# 访问第一行的字符
mat[1,] # 1 4
# 操作第一行数据
3 * mat[,1] # 3 6 9
# 访问一个特定数据
mat[3,2] # 6
# 转置整个矩阵(译者注:变成 2 行 3 列)
t(mat)
# =>
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 4 5 6
# 使用 cbind() 函数把两个矩阵按列合并,形成新的矩阵
mat2 <- cbind(1:4, c("dog", "cat", "bird", "dog"))
mat2
# =>
# [,1] [,2]
# [1,] "1" "dog"
# [2,] "2" "cat"
# [3,] "3" "bird"
# [4,] "4" "dog"
class(mat2) # matrix
# Again, note what happened!
# 注意
# 因为矩阵内部元素必须包含同样的类型
# 所以现在每一个元素都转化成字符串
c(class(mat2[,1]), class(mat2[,2]))
# 按行合并两个向量,建立新的矩阵
mat3 <- rbind(c(1,2,4,5), c(6,7,0,4))
mat3
# =>
# [,1] [,2] [,3] [,4]
# [1,] 1 2 4 5
# [2,] 6 7 0 4
# 哈哈,数据类型都一样的,没有发生强制转换,生活真美好
# 二维(不同的元素类型)
# 利用 data frame 可以将不同类型数据放在一起
dat <- data.frame(c(5,2,1,4), c("dog", "cat", "bird", "dog"))
names(dat) <- c("number", "species") # 给数据列命名
class(dat) # "data.frame"
dat
# =>
# number species
# 1 5 dog
# 2 2 cat
# 3 1 bird
# 4 4 dog
class(dat$number) # "numeric"
class(dat[,2]) # "factor"
# data.frame() 会将字符向量转换为 factor 向量
# 有很多精妙的方法来获取 data frame 的子数据集
dat$number # 5 2 1 4
dat[,1] # 5 2 1 4
dat[,"number"] # 5 2 1 4
# 多维(相同元素类型)
# 使用 arry 创造一个 n 维的表格
# You can make a two-dimensional table (sort of like a matrix)
# 你可以建立一个 2 维表格(有点像矩阵)
array(c(c(1,2,4,5),c(8,9,3,6)), dim=c(2,4))
# =>
# [,1] [,2] [,3] [,4]
# [1,] 1 4 8 3
# [2,] 2 5 9 6
#你也可以利用数组建立一个三维的矩阵
array(c(c(c(2,300,4),c(8,9,0)),c(c(5,60,0),c(66,7,847))), dim=c(3,2,2))
# =>
# , , 1
#
# [,1] [,2]
# [1,] 2 8
# [2,] 300 9
# [3,] 4 0
#
# , , 2
#
# [,1] [,2]
# [1,] 5 66
# [2,] 60 7
# [3,] 0 847
#列表(多维的,不同类型的)
# R语言有列表的形式
list1 <- list(time = 1:40)
list1$price = c(rnorm(40,.5*list1$time,4)) # 随机
list1
# You can get items in the list like so
# 你可以这样获得列表的元素
list1$time
# You can subset list items like vectors
# 你也可以和矢量一样获取他们的子集
list1$price[4]
#########################
# apply()函数家族
#########################
# 还记得 mat 么?
mat
# =>
# [,1] [,2]
# [1,] 1 4
# [2,] 2 5
# [3,] 3 6
# Use apply(X, MARGIN, FUN) to apply function FUN to a matrix X
# 使用(X, MARGIN, FUN)将函数 FUN 应用到矩阵 X 的行 (MAR = 1) 或者 列 (MAR = 2)
# That is, R does FUN to each row (or column) of X, much faster than a
# R 在 X 的每一行/列使用 FUN,比循环要快很多
apply(mat, MAR = 2, myFunc)
# =>
# [,1] [,2]
# [1,] 3 15
# [2,] 7 19
# [3,] 11 23
# 还有其他家族函数 ?lapply, ?sapply
# 不要被吓到,虽然许多人在此都被搞混
# plyr 程序包的作用是用来改进 apply() 函数家族
install.packages("plyr")
require(plyr)
?plyr
#########################
# 载入数据
#########################
# "pets.csv" 是网上的一个文本
pets <- read.csv("http://learnxinyminutes.com/docs/pets.csv")
pets
head(pets, 2) # 前两行
tail(pets, 1) # 最后一行
# 以 .csv 格式来保存数据集或者矩阵
write.csv(pets, "pets2.csv") # 保存到新的文件 pets2.csv
# set working directory with setwd(), look it up with getwd()
# 使用 setwd() 改变工作目录,使用 getwd() 查看当前工作目录
# 尝试使用 ?read.csv 和 ?write.csv 来查看更多信息
#########################
# 画图
#########################
# 散点图
plot(list1$time, list1$price, main = "fake data") # 译者注:横轴 list1$time,纵轴 wlist1$price,标题 fake data
# 回归图
linearModel <- lm(price ~ time, data = list1) # 译者注:线性模型,数据集为list1,以价格对时间做相关分析模型
linearModel # 拟合结果
# 将拟合结果展示在图上,颜色设为红色
abline(linearModel, col = "red")
# 也可以获取各种各样漂亮的分析图
plot(linearModel)
# 直方图
hist(rpois(n = 10000, lambda = 5), col = "thistle") # 译者注:统计频数直方图
# 柱状图
barplot(c(1,4,5,1,2), names.arg = c("red","blue","purple","green","yellow"))
# 可以尝试着使用 ggplot2 程序包来美化图片
install.packages("ggplot2")
require(ggplot2)
?ggplot2
================================================
FILE: learnruby-cn.rb
================================================
# 这是单行注释
=begin
这是多行注释
没人用这个
你也不该用
=end
# 首先,也是最重要的,所有东西都是对象
# 数字是对象
3.class #=> Fixnum
3.to_s #=> "3"
# 一些基本的算术符号
1 + 1 #=> 2
8 - 1 #=> 7
10 * 2 #=> 20
35 / 5 #=> 7
# 算术符号只是语法糖而已
# 实际上是调用对象的方法
1.+(3) #=> 4
10.* 5 #=> 50
# 特殊的值也是对象
nil # 空
true # 真
false # 假
nil.class #=> NilClass
true.class #=> TrueClass
false.class #=> FalseClass
# 相等运算符
1 == 1 #=> true
2 == 1 #=> false
# 不等运算符
1 != 1 #=> false
2 != 1 #=> true
!true #=> false
!false #=> true
# 除了false自己,nil是唯一的值为false的对象
!nil #=> true
!false #=> true
!0 #=> false
# 更多比较
1 < 10 #=> true
1 > 10 #=> false
2 <= 2 #=> true
2 >= 2 #=> true
# 字符串是对象
'I am a string'.class #=> String
"I am a string too".class #=> String
placeholder = "use string interpolation"
"I can #{placeholder} when using double quoted strings"
#=> "I can use string interpolation when using double quoted strings"
# 输出值
puts "I'm printing!"
# 变量
x = 25 #=> 25
x #=> 25
# 注意赋值语句返回了赋的值
# 这意味着你可以用多重赋值语句
x = y = 10 #=> 10
x #=> 10
y #=> 10
# 按照惯例,用 snake_case 作为变量名
snake_case = true
# 使用具有描述性的运算符
path_to_project_root = '/good/name/'
path = '/bad/name/'
# 符号(Symbols,也是对象)
# 符号是不可变的,内部用整数类型表示的可重用的值。
# 通常用它代替字符串来有效地表示有意义的值。
:pending.class #=> Symbol
status = :pending
status == :pending #=> true
status == 'pending' #=> false
status == :approved #=> false
# 数组
# 这是一个数组
[1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]
# 数组可以包含不同类型的元素
array = [1, "hello", false] #=> => [1, "hello", false]
# 数组可以被索引
# 从前面开始
array[0] #=> 1
array[12] #=> nil
# 像运算符一样,[var]形式的访问
# 也就是一个语法糖
# 实际上是调用对象的[] 方法
array.[] 0 #=> 1
array.[] 12 #=> nil
# 从尾部开始
array[-1] #=> 5
# 同时指定开始的位置和结束的位置
array[2, 4] #=> [3, 4, 5]
# 或者指定一个范围
array[1..3] #=> [2, 3, 4]
# 像这样往数组增加一个元素
array << 6 #=> [1, 2, 3, 4, 5, 6]
# 哈希表是Ruby的键值对的基本数据结构
# 哈希表由大括号定义
hash = {'color' => 'green', 'number' => 5}
hash.keys #=> ['color', 'number']
# 哈希表可以通过键快速地查询
hash['color'] #=> 'green'
hash['number'] #=> 5
# 查询一个不存在地键将会返回nil
hash['nothing here'] #=> nil
# 用 #each 方法来枚举哈希表:
hash.each do |k, v|
puts "#{k} is #{v}"
end
# 从Ruby 1.9开始, 用符号作为键的时候有特别的记号表示:
new_hash = { defcon: 3, action: true}
new_hash.keys #=> [:defcon, :action]
# 小贴士:数组和哈希表都是可枚举的
# 它们可以共享一些有用的方法,比如each, map, count 等等
# 控制流
if true
"if statement"
elsif false
"else if, optional"
else
"else, also optional"
end
for counter in 1..5
puts "iteration #{counter}"
end
#=> iteration 1
#=> iteration 2
#=> iteration 3
#=> iteration 4
#=> iteration 5
# 然而
# 没人用for循环
# 用`each`来代替,就像这样
(1..5).each do |counter|
puts "iteration #{counter}"
end
#=> iteration 1
#=> iteration 2
#=> iteration 3
#=> iteration 4
#=> iteration 5
counter = 1
while counter <= 5 do
puts "iteration #{counter}"
counter += 1
end
#=> iteration 1
#=> iteration 2
#=> iteration 3
#=> iteration 4
#=> iteration 5
grade = 'B'
case grade
when 'A'
puts "Way to go kiddo"
when 'B'
puts "Better luck next time"
when 'C'
puts "You can do better"
when 'D'
puts "Scraping through"
when 'F'
puts "You failed!"
else
puts "Alternative grading system, eh?"
end
# 函数
def double(x)
x * 2
end
# 函数 (以及所有的方法块) 隐式地返回了最后语句的值
double(2) #=> 4
# 当不存在歧义的时候括号是可有可无的
double 3 #=> 6
double double 3 #=> 12
def sum(x,y)
x + y
end
# 方法的参数通过逗号分隔
sum 3, 4 #=> 7
sum sum(3,4), 5 #=> 12
# yield
# 所有的方法都有一个隐式的块参数
# 可以用yield参数调用
def surround
puts "{"
yield
puts "}"
end
surround { puts 'hello world' }
# {
# hello world
# }
# 用class关键字定义一个类
class Human
# 一个类变量,它被这个类地所有实例变量共享
@@species = "H. sapiens"
# 构造函数
def initialize(name, age=0)
# 将参数name的值赋给实例变量@name
@name = name
# 如果没有给出age, 那么会采用参数列表中地默认地值
@age = age
end
# 基本的 setter 方法
def name=(name)
@name = name
end
# 基本地 getter 方法
def name
@name
end
# 一个类方法以self.开头
# 它可以被类调用,但不能被类的实例调用
def self.say(msg)
puts "#{msg}"
end
def species
@@species
end
end
# 类的例子
jim = Human.new("Jim Halpert")
dwight = Human.new("Dwight K. Schrute")
# 让我们来调用一些方法
jim.species #=> "H. sapiens"
jim.name #=> "Jim Halpert"
jim.name = "Jim Halpert II" #=> "Jim Halpert II"
jim.name #=> "Jim Halpert II"
dwight.species #=> "H. sapiens"
dwight.name #=> "Dwight K. Schrute"
# 调用对象的方法
Human.say("Hi") #=> "Hi"
================================================
FILE: learnswift-cn.swift
================================================
//
// 基础
//
println("Hello, world")
var myVariable = 42
let myConstant = 3.1415926
let explicitDouble: Double = 70
let label = "some text " + String(myVariable) // Casting
let piText = "Pi = \(myConstant)" // String interpolation
var optionalString: String? = "optional" // Can be nil
optionalString = nil
//
// 数组与字典(关联数组)
//
// 数组
var shoppingList = ["catfish", "water", "lemons"]
shoppingList[1] = "bottle of water"
let emptyArray = String[]()
// 字典
var occupations = [
"Malcolm": "Captain",
"kaylee": "Mechanic"
]
occupations["Jayne"] = "Public Relations"
let emptyDictionary = Dictionary<String, Float>()
//
// 控制流
//
// 用于数组的for 循环
let myArray = [1, 1, 2, 3, 5]
for value in myArray {
if value == 1 {
println("One!")
} else {
println("Not one!")
}
}
// 用于字典的for 循环
for (key, value) in dict {
println("\(key): \(value)")
}
// 用于区间的for 循环
for i in -1...1 { // [-1, 0, 1]
println(i)
}
// 使用 .. 表示的区间不包含最后一个元素 [-1,0,1)
// while 循环
var i = 1
while i < 1000 {
i *= 2
}
// do-while 循环
do {
println("hello")
} while 1 == 2
// Switch
let vegetable = "red pepper"
switch vegetable {
case "celery":
let vegetableComment = "Add some raisins and make ants on a log."
case "cucumber", "watercress":
let vegetableComment = "That would make a good tea sandwich."
case let x where x.hasSuffix("pepper"):
let vegetableComment = "Is it a spicy \(x)?"
default: // 必须 (为了覆盖所有可能的输入)
let vegetableComment = "Everything tastes good in soup."
}
//
// 函数
//
// 函数是一等类型,这意味着可以在函数中构建函数
// 并且可以被传递
// 函数
func greet(name: String, day: String) -> String {
return "Hello \(name), today is \(day)."
}
greet("Bob", "Tuesday")
// 使用多元数组返回多返回值的函数
func getGasPrices() -> (Double, Double, Double) {
return (3.59, 3.69, 3.79)
}
// 不定参数
func setup(numbers: Int...) {}
// 传递、返回函数
func makeIncrementer() -> (Int -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(7)
//
// 闭包
//
// 函数是特殊的闭包({})
// 闭包示例.
// `->` 分隔参数和返回类型
// `in` 分隔闭包头和闭包体
numbers.map({
(number: Int) -> Int in
let result = 3 * number
return result
})
// 当类型已知时,可以这样做:
var numbers = [1, 2, 6]
numbers = numbers.map({ number in 3 * number })
print(numbers) // [3, 6, 18]
//
// 类
//
// 类的全部方法和属性都是public 的
// 如果你在一个数据结构中只需储存数据,
// 应使用 `struct`
// 集成自`Shape` 类的简单的类`Square
class Rect: Shape {
var sideLength: Int = 1
// Custom getter and setter property
var perimeter: Int {
get {
return 4 * sideLength
}
set {
sideLength = newValue / 4
}
}
init(sideLength: Int) {
super.init()
self.sideLength = sideLength
}
func shrink() {
if sideLength > 0 {
--sideLength
}
}
override func getArea() -> Int {
return sideLength * sideLength
}
}
var mySquare = new Square(sideLength: 5)
print(mySquare.getArea()) // 25
mySquare.shrink()
print(mySquare.sideLength) // 4
// 如果你不需要自定义getter 和setter,
// 但仍希望在获取或设置一个属性之前或之后运行
// 一些代码,你可以使用`willSet` 和 `didSet`
//
// 枚举类型
//
// 枚举类型可以是某种指定的类型,抑或自成一种类型
// 像类一样,枚举类型可以包含方法
enum Suit {
case Spades, Hearts, Diamonds, Clubs
func getIcon() -> String {
switch self {
case .Spades: return "♤"
case .Hearts: return "♡"
case .Diamonds: return "♢"
case .Clubs: return "♧"
}
}
}
//
// 其它
//
// `协议(protocol)`: 与Java 的接口(Interface) 类似.
// `扩展(extension)`: 为现有类型添加额外特性
// 泛型: 与Java 相似。使用`where` 关键字指定
// 泛型的要求.
gitextract_caczyvz4/ ├── README.md ├── learnbash-cn.sh ├── learnc-cn.c ├── learncsharp-cn.cs ├── learncss-cn.css ├── learngo-cn.go ├── learnlua-cn.lua ├── learnperl-cn.pl ├── learnphp-cn.php ├── learnpython-cn.py ├── learnpython3-cn.py ├── learnr-cn.r ├── learnruby-cn.rb └── learnswift-cn.swift
SYMBOL INDEX (125 symbols across 7 files)
FILE: learnc-cn.c
type days (line 12) | enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}
function main (line 34) | int main() {
function add_two_ints (line 412) | int add_two_ints(int x1, int x2){
function str_reverse (line 427) | void str_reverse(char *str_in){
function testFunc (line 446) | void testFunc() {
function testFunc (line 452) | void testFunc() {
type my_type (line 463) | typedef int my_type;
type rectangle (line 468) | struct rectangle {
function function_1 (line 477) | void function_1(){
type rect (line 496) | typedef struct rectangle rect;
function area (line 498) | int area(rect r){
function area (line 504) | int area(const rect *r)
function str_reverse_through_pointer (line 520) | void str_reverse_through_pointer(char *str_in) {
FILE: learncsharp-cn.cs
class LearnCSharp (line 26) | public class LearnCSharp
method Syntax (line 29) | public static void Syntax()
method Classes (line 309) | public static void Classes()
method Main (line 331) | public static void Main(string[] args)
method MethodSignatures (line 342) | public // 可见性
method MethodSignature (line 356) | public static void MethodSignature(string maxCount)
method SetDefault (line 363) | public static TValue SetDefault<TKey, TValue>(
method IterateAndPrint (line 375) | public static void IterateAndPrint<T>(T toPrint) where T: IEnumerable<...
method OtherInterestingFeatures (line 383) | public static void OtherInterestingFeatures()
class Extensions (line 517) | public static class Extensions
method Print (line 520) | public static void Print(this object obj)
class Bicycle (line 531) | public class Bicycle
type BikeBrand (line 566) | public enum BikeBrand
method Bicycle (line 589) | public Bicycle()
method Bicycle (line 600) | public Bicycle(int startCadence, int startSpeed, int startGear,
method Bicycle (line 613) | public Bicycle(int startCadence, int startSpeed, BikeBrand brand) :
method SpeedUp (line 625) | public void SpeedUp(int increment = 1)
method SlowDown (line 630) | public void SlowDown(int decrement = 1)
method Info (line 661) | public virtual string Info()
method DidWeCreateEnoughBycles (line 673) | public static bool DidWeCreateEnoughBycles()
class PennyFarthing (line 683) | class PennyFarthing : Bicycle
method PennyFarthing (line 688) | public PennyFarthing(int startCadence, int startSpeed) :
method Info (line 705) | public override string Info()
type IJumpable (line 714) | interface IJumpable
method Jump (line 716) | void Jump(int meters);
type IBreakable (line 719) | interface IBreakable
method Jump (line 728) | public void Jump(int meters)
class BikeRespository (line 747) | public class BikeRespository : DbSet
method BikeRespository (line 749) | public BikeRespository()
FILE: learngo-cn.go
function main (line 19) | func main() {
function beyondHello (line 30) | func beyondHello() {
function learnMultiple (line 41) | func learnMultiple(x, y int) (sum, prod int) {
function learnTypes (line 46) | func learnTypes() {
function learnMemory (line 95) | func learnMemory() (p, q *int) {
function expensiveComputation (line 105) | func expensiveComputation() int {
function learnFlowControl (line 109) | func learnFlowControl() {
type Stringer (line 161) | type Stringer interface
type pair (line 166) | type pair struct
method String (line 171) | func (p pair) String() string { // p被叫做“接收器”
method ServeHTTP (line 256) | func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
function learnInterfaces (line 177) | func learnInterfaces() {
function learnErrorHandling (line 194) | func learnErrorHandling() {
function inc (line 212) | func inc(i int, c chan int) {
function learnConcurrency (line 217) | func learnConcurrency() {
function learnWebProgramming (line 249) | func learnWebProgramming() {
FILE: learnphp-cn.php
function my_function (line 316) | function my_function () {
function add (line 325) | function add ($x, $y = 1) { // $y 是可选参数,默认值为 1
function foo (line 343) | function foo ($x, $y, $z) {
function bar (line 348) | function bar ($x, $y) {
class MyClass (line 402) | class MyClass
method __construct (line 415) | public function __construct($instanceProp) {
method myMethod (line 421) | public function myMethod()
method youCannotOverrideMe (line 426) | final function youCannotOverrideMe()
method myStaticMethod (line 430) | public static function myStaticMethod()
class MyOtherClass (line 451) | class MyOtherClass extends MyClass
method printProtectedProperty (line 453) | function printProtectedProperty()
method myMethod (line 459) | function myMethod()
class YouCannotExtendMe (line 470) | final class YouCannotExtendMe
class MyMapClass (line 475) | class MyMapClass
method __get (line 479) | public function __get($key)
method __set (line 484) | public function __set($key, $value)
type InterfaceOne (line 498) | interface InterfaceOne
method doSomething (line 500) | public function doSomething();
type InterfaceTwo (line 503) | interface InterfaceTwo
method doSomethingElse (line 505) | public function doSomethingElse();
type InterfaceThree (line 509) | interface InterfaceThree extends InterfaceTwo
method doAnotherContract (line 511) | public function doAnotherContract();
class MyAbstractClass (line 514) | abstract class MyAbstractClass implements InterfaceOne
class MyConcreteClass (line 519) | class MyConcreteClass extends MyAbstractClass implements InterfaceTwo
method doSomething (line 521) | public function doSomething()
method doSomethingElse (line 526) | public function doSomethingElse()
class SomeOtherClass (line 534) | class SomeOtherClass implements InterfaceOne, InterfaceTwo
method doSomething (line 536) | public function doSomething()
method doSomethingElse (line 541) | public function doSomethingElse()
type MyTrait (line 554) | trait MyTrait
method myTraitMethod (line 556) | public function myTraitMethod()
class MyTraitfulClass (line 562) | class MyTraitfulClass
class MyClass (line 589) | class MyClass
method __construct (line 415) | public function __construct($instanceProp) {
method myMethod (line 421) | public function myMethod()
method youCannotOverrideMe (line 426) | final function youCannotOverrideMe()
method myStaticMethod (line 430) | public static function myStaticMethod()
FILE: learnpython-cn.py
function add (line 307) | def add(x, y):
function varargs (line 318) | def varargs(*args):
function keyword_args (line 325) | def keyword_args(**kwargs):
function all_the_args (line 332) | def all_the_args(*args, **kwargs):
function create_adder (line 349) | def create_adder(x):
class Human (line 373) | class Human(object):
method __init__ (line 379) | def __init__(self, name):
method say (line 384) | def say(self, msg):
method get_species (line 390) | def get_species(cls):
method grunt (line 395) | def grunt():
FILE: learnpython3-cn.py
function add (line 378) | def add(x, y):
function varargs (line 390) | def varargs(*args):
function keyword_args (line 397) | def keyword_args(**kwargs):
function all_the_args (line 405) | def all_the_args(*args, **kwargs):
function setX (line 425) | def setX(num):
function setGlobalX (line 430) | def setGlobalX(num):
function create_adder (line 441) | def create_adder(x):
class Human (line 466) | class Human(object):
method __init__ (line 474) | def __init__(self, name):
method say (line 479) | def say(self, msg):
method get_species (line 484) | def get_species(cls):
method grunt (line 489) | def grunt():
function double_numbers (line 546) | def double_numbers(iterable):
function beg (line 570) | def beg(target_function):
function say (line 582) | def say(say_please=False):
FILE: learnruby-cn.rb
function double (line 228) | def double(x)
function sum (line 240) | def sum(x,y)
function surround (line 253) | def surround
class Human (line 267) | class Human
method initialize (line 273) | def initialize(name, age=0)
method name= (line 281) | def name=(name)
method name (line 286) | def name
method say (line 292) | def self.say(msg)
method species (line 296) | def species
Condensed preview — 14 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (148K chars).
[
{
"path": "README.md",
"chars": 1128,
"preview": "# Learn X in Y minutes\n在线编程语言速学网,C++、CSS、java、json、PHP、python、swift等各种语言的快速学习教程。\n- [C](https://github.com/Y-Dian/LearnXi"
},
{
"path": "learnbash-cn.sh",
"chars": 2471,
"preview": "\n#!/bin/bash\n# 脚本的第一行叫 shebang,用来告知系统如何执行该脚本:\n# 参见: http://en.wikipedia.org/wiki/Shebang_(Unix)\n# 如你所见,注释以 # 开头,shebang "
},
{
"path": "learnc-cn.c",
"chars": 12414,
"preview": "\n// 单行注释以//开始。(仅适用于C99或更新的版本。)\n\n/*\n多行注释是这个样子的。(C89也适用。)\n*/\n\n// 常数: #define 关键词\n#define DAYS_IN_YEAR 365\n\n// 以枚举的方式定义常数\ne"
},
{
"path": "learncsharp-cn.cs",
"chars": 22466,
"preview": "\n// 单行注释以 // 开始\n/*\n多行注释是这样的\n*/\n/// <summary>\n/// XML文档注释\n/// </summary>\n\n// 声明应用用到的命名空间\nusing System;\nusing System.Colle"
},
{
"path": "learncss-cn.css",
"chars": 2493,
"preview": "\n/* 注释 */\n\n/* ####################\n ## 选择器\n ####################*/\n\n/* 一般而言,CSS的声明语句非常简单。 */\n选择器 { 属性: 值; /* 更多属性..."
},
{
"path": "learngo-cn.go",
"chars": 6350,
"preview": "\n// 单行注释\n/* 多行\n 注释 */\n\n// 导入包的子句在每个源文件的开头。\n// Main比较特殊,它用来声明可执行文件,而不是一个库。\npackage main\n\n// Import语句声明了当前文件引用的包。\nimpor"
},
{
"path": "learnlua-cn.lua",
"chars": 8606,
"preview": "\n-- 单行注释以两个连字符开头 \n\n--[[ \n 多行注释\n--]]\n\n---------------------------------------------------- \n-- 1. 变量和流程控制\n-----------"
},
{
"path": "learnperl-cn.pl",
"chars": 2025,
"preview": "# 单行注释以#号开头\n\n\n#### Perl的变量类型\n\n# 变量以$号开头。\n# 合法变量名以英文字母或者下划线起始,\n# 后接任意数目的字母、数字或下划线。\n\n### Perl有三种主要的变量类型:标量、数组和哈希。\n\n## 标"
},
{
"path": "learnphp-cn.php",
"chars": 9896,
"preview": "\n<?php // PHP必须被包围于 <?php ? > 之中\n\n// 如果你的文件中只有php代码,那么最好省略结束括号标记\n\n// 这是单行注释的标志\n\n# 井号也可以,但是//更常见\n\n/*\n 这是多行注释\n*/\n\n// 使"
},
{
"path": "learnpython-cn.py",
"chars": 7932,
"preview": "\n\n# 单行注释\n\"\"\" 多行字符串可以用\n 三个引号包裹,不过这也可以被当做\n 多行注释\n\"\"\"\n\n####################################################\n## 1. 原始数据"
},
{
"path": "learnpython3-cn.py",
"chars": 10902,
"preview": "\n\n# 用井字符开头的是单行注释\n\n\"\"\" 多行字符串用三个引号\n 包裹,也常被用来做多\n 行注释\n\"\"\"\n\n####################################################\n## 1. "
},
{
"path": "learnr-cn.r",
"chars": 10368,
"preview": "\n# 评论以 # 开始\n\n# R 语言原生不支持 多行注释\n# 但是你可以像这样来多行注释\n\n# 在窗口里按回车键可以执行一条命令\n\n\n####################################################"
},
{
"path": "learnruby-cn.rb",
"chars": 4248,
"preview": "\n# 这是单行注释\n\n=begin\n这是多行注释\n没人用这个\n你也不该用\n=end\n\n# 首先,也是最重要的,所有东西都是对象\n\n# 数字是对象\n\n3.class #=> Fixnum\n\n3.to_s #=> \"3\"\n\n\n# 一些基本的算术"
},
{
"path": "learnswift-cn.swift",
"chars": 3460,
"preview": "\n//\n// 基础\n//\n\nprintln(\"Hello, world\")\nvar myVariable = 42\nlet myConstant = 3.1415926\nlet explicitDouble: Double = 70\nlet"
}
]
About this extraction
This page contains the full source code of the Y-Dian/LearnXinYminutes GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 14 files (102.3 KB), approximately 42.7k tokens, and a symbol index with 125 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.