别名。一初始化,就必须指向某个对象,不能指向引用。
1 | int ival = 1024; |
不能用于修改其所指对象的值,常量对象的指针,只能使用指向常量的指针。
1 | const double pi = 3.14; |
常量指针必须初始化,且初始化完成后,其值不能再改变,也就是说只能一直指向某一个地址。可以通过此指针改变所指向对象的值。
1 | int errNumb = 0; |
以const double *const pip = &pi
为例,离pip最近的是const,说明pip本身的值不能改变,在往左,pip的类型是一个指针,说明pip是一个常量指针;在往左,说明pip是一个常量指针,它指向的对象是double类型;再往左,说明pip是一个常量指针,它指向的对象是一个double型常量的。
用def定义的变量时无类型的变量,这里所说的无类型的变量,并不表示该变量就不属于某一个类型了,def修饰变量正是Groovy为动态语言的标记,大概def修饰变量就相当于Java中Object来修饰变量吧。如果通过使用def关键字使用可选类型,那么整数的类型将是可变的:它取决于这个类型实际包含的值。
1 | assert a instanceof Integer |
如果所定义的函数没有参数,那么必须在调用的时候加上括号。
要有返回值的类型声明,如def、void、String等。
可以使用return返回值,若不写,则默认返回最后一行的值,没有则为null。
A closure in Groovy is an open, anonymous, block of code that can take arguments, return a value and be assigned to a variable. A closure may reference variables declared in its surrounding scope. In opposition to the formal definition of a closure, Closure in the Groovy language can also contain free variables which are defined outside of its surrounding scope.Apache Groovy Doc
1 | { println 'hi' } |
1 | def str='hello world' |
1 | def timesThree = { |
1 | def p = new Person(name:'Jessica', age:42) |
至此基本的东西差不多解决了。
其实关于堆栈的问题在脑海中盘旋了挺久的了。从C语言开始,到数据结构,再到现在的Java,它一直在!现在就让我们从头开始吧。
首先应该明确堆和栈是不同的东西,其次数据结构中的堆和栈与编程语言中的堆和栈不是同一个概念。
栈:即Stack,是一个LIFO队列。对它的操作有pop(),push(),peek()等。
堆:即Heap,是一棵完全二叉树(heap的某一种),它的特点是父节点的值大于(小于)两个子节点的值(分别称为大顶堆和小顶堆)。
具体内容可以参考后续关于数据结构的系列博客。
1 | int a = 0; //全局初始化区 |
一个比较直观的感受就是使用malloc()函数分配出来的空间在堆上,其它经过系统初始化的在栈上。堆上的不能自己回收,栈上的会随着函数结束后自动回收。
堆区:存放所有new出来的对象本身
栈区:存放基本类型的变量数据和对象的引用
静态域:存放静态成员(由static定义)
常量池:存放字符串常量和基本类型常量(public static final)
很久没用过Python了,熟悉一下用法准备ms。
1 | input('input:') var= |
暂时理解input()读入一行数据,且可以加入提示信息。
读入一个整数:
1 | s = input('birth: ') |
# 注释某行中其后的内容。
缩进代替C系列语言中的大括号。
大小写敏感。
字符串可用''或""包裹, \可用于转义。\n\t等
r’’表示’’内部的字符串默认不转义
'''表示多行输入
1 | print(r'\\\t\\') |
空值是一个特殊的值,用None表示。None不能理解为0,因为0是有意义的,而None是一个特殊的空值。
用全部大写的变量名表示常量。
三种除法,//地板除,/整除,得到浮点数,%取余。
在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。
ord()函数获取字符的整数表示,chr()函数把编码转换为对应的字符。
格式化:
1 | 'Hi, %s, you have $%d.' % ('Michael', 1000000) |
1 | 1] fruits[- |
不可更改的list,声明用()
当你定义一个tuple时,在定义的时候,tuple的元素就必须被确定下来。
t = (1)定义的是自然数1,要定义成tuple需要加‘,’,规则。
t = (‘a’, ‘b’, [‘A’, ‘B’])其中的list是可变的。
1 | 'Michael': 95, 'Bob': 75, 'Tracy': 85} d = { |
1 | 'Thomas' in d |
1 | s = set([1, 2, 3]) |
可以对集合进行&和|操作。
1 | age = 3 |
可打印list、tuple中的数据。
1 | names = ['Michael', 'Bob', 'Tracy'] |
1 | sum = 0 |
同C系列语言
1 | abs # 变量a指向abs函数 a = |
1 | def my_abs(x): |
默认参数
1 | def power(x, n=2): |
可变参数
1 | def calc(*numbers): |
*nums表示把nums这个list的所有元素作为可变参数传进去。
关键字参数
1 | def person(name, age, **kw): |
**extra表示把extra这个dict的所有key-value用关键字参数传入到函数的**kw参数,kw将获得一个dict,注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra
命名关键字参数
1 | def person(name, age, *, city, job): |
参数组合
参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
支持递归
1 | L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack'] |
1 | 'a': 1, 'b': 2, 'c': 3} d = { |
1 | for x in range(1, 11)] [x * x |
1 | def fib(max): |
函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
把list、dict、str等Iterable变成Iterator可以使用iter()函数:
凡是可作用于for循环的对象都是Iterable类型;
凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
Python的for循环本质上就是通过不断调用next()函数实现的,例如:
1 | for x in [1, 2, 3, 4, 5]: |
1 | def add(x, y, f): |
1 | def f(x): |
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
1 | from functools import reduce |
1 | def is_odd(n): |
1 | sorted([36, 5, -12, 9, -21], key=abs) |