nodejs编程
❶ 阮一峰nodejs教程
手把手教你使用nodejs编写cli(命令行)1、使用nodeindex.js这种方式调用的话固然简单灵活,但是严重依赖脚本路径,一旦目录结构发生变动,写在scripts的命令就要更改一次;但是使用npm安装之后,本地的cli脚本就被拉到node_moles里面,目录结构变动对其影响不大。
2、,安装完成node,node有自带的npm,可以直接在cmd中,找到nodeJs安装的路径下,进行命令行全局安装vue-cli。
3、在Node.js中,有一个内置的命令行界面(CLI),它允许你通过命令行直接执行javaScript代码,而不需要先创建和运行一个完整的文件或者应用程序。
自学web前端开发,请问从何入手呢?1、JS编程的调试非常简单,打开浏览器控制台(我个人比较钟爱Chrome)。如图:1console标签:这个标签,可以打印我们开发时,JS引擎为我们抛出的异常。我们可以根据这个异常的信息,来分析错误原因。
2、对于想学习web前端的同学来说:首先是自学,其实自学也不是不可以,只要有毅力能坚持,自己学习是完全没有问题的,现在有很多同学也是自己找资料视频来学习。
3、掌握web前端开发技术的同时,适当的学习一些后台开发语言(java,php等)也是一个不错的选择。
4、不管是零基础还是有基础的朋友,建议还是报一个专业的培训班进行系统的学习,培训班推荐网时代教育,网时代教育是一家集互联网营销师、UI/UE交互设计师、平面设计师、Web前端工程师、Java工程师等课程为一体的IT培训机构。
5、web前端目前需求量多,容易上手,对于自学能力比较强的,很快就掌握,出去工作找经验,对以后职业发展有很大的帮助。新手自学it是比较困难的,在学前端开发过程中各种问题不懂也是难免的。
6、如果是零基础,不建议自学web前端开发,建议去专业的培训学校系统学习,推荐千锋教育,千锋以政策为引导,不断完善国内特色现代职业教育体系建设,构建品质教育,加大创新型人才培养力度。
为什么昨天阮一峰老师发布全栈工程师资料中主要学习react和node,js1、NodeJs是基于JavaScript的,可以做为后台开发的语言.提供了很多系统级的API,如文件操作、网络编程等.用事件驱动,异步编程,主要是为后台网络服务设计。
2、最好的)编程语言,主要作为前端开发中用来增加网页的动态功能。NodeJs是基于JavaScript的,可以做为后台开发的语言.提供了很多系统级的API,如文件操作、网络编程等.用事件驱动,异步编程,主要是为后台网络服务设计。
3、就目前来讲,肯定还是nodejs,有了nodejs,前端可以不在依赖后端,而且有了npm这个生态圈。
前端开发需要学什么啊?
1、前端开发需要学习的内容包括PC网站布局、HTML5+CSS3基础项目、webapp页面布局等。学习web前端开发,web开发工具有frontpage,可以使用word让人轻松学习frontpage,另一个常见的是Dreamweaver,这两个是最常用的HTML网页制作工具。
2、需要学习如下内容:HTML语言掌握HTML是网页的核心,是一种制作万维网页面的标准语言,是万维网浏览器使用的一种语言,它消除了不同计算机之间信息交流的障碍。
3、响应式设计显然是目前web前端开发领域的主要趋势之一,响应式网站设计是一种网络页面设计布局,其理念是:集中创建页面的图片排版大小,可以智能地根据用户行为以及使用的设备环境进行相对应的布局。
4、web前端开发中需要掌握的技术:学习HTML,这是最简单,最基本的是要掌握div,formtable、Ulli、P、跨度、字体这些标签,这些都是最常用的,尤其是DIV和表格,DIV,表也可以用于布局,但不灵活,和用于基本表处理数据。
5、前端开发需要学HTML、CSS和JavaScript。这是做前必须要学的东西。
阮一峰的介绍1、阮一峰,70后,英文名Frank。他原是上海财经大学世界经济博士研究生。主要研究宏观金融、货币政策与美国经济。于2008年6月获得博士学位。目前在上海一所当地大学(上海金融学院国际经贸学院)任教。
2、阮一峰是个牛人,他的博克非常值得读。根据东升做的人肉搜索,他原是上海财经大学世界经济博士研究生。主要研究宏观金融、货币政策与美国经济。今年(2008年)6月获得博士学位。恭贺!不知道他现在哪里高就。
3、作为linux以及git的主要创造者,Linus的编程水平是毋庸置疑的。但是Linux的主要编程语言是C,从这个意义上说,他的C++可能不太好。
❷ 如何编写 Node.js 扩展
一、编写Node.js原生扩展
Node.js是一个强大的平台,理想状态下一切都都可以用javascript写成。然而,你可能还会用到许多遗留的库和系统,这样的话使用c++编写Node.JS扩展会是一个不错的注意。
以下所有例子的源代码可在node扩展示例中找到 。
编写Node.js C + +扩展很大程度上就像是写V8的扩展; Node.js增加了一些接口,但大部分时间你都是在使原始的V8数据类型和方法,为了理解以下的代码,你必须首先阅读V8引擎嵌入指南。
Javascript版本的Hello World
在讲解C++版本的例子之前,先让我们来看看在Node.js中用Javascript编写的等价模块是什么样子。这是一个最简单的Hello World,也不是通过HTTP,但它展示了node模块的结构,而其接口也和大多数C++扩展要提供的接口差不多:
HelloWorldJs = function() {
this.m_count = 0;
};
HelloWorldJs.prototype.hello = function()
{
this.m_count++;
return “Hello World”;
};
exports.HelloWorldJs = HelloWorldJs;
正如你所看到的,它使用prototype为HelloWorldJs类创建了一个新的方法。请注意,上述代码通过将HelloWorldJS添加到exports变量来暴露构造函数。
要在其他地方使用该模块,请使用如下代码:
var helloworld = require(‘helloworld_js’);
var hi = new helloworld.HelloWorldJs();
console.log(hi.hello()); // prints “Hello World” to stdout
C++版本的Hello World
要开始编写C++扩展,首先要能够编译Node.js(请注意,我们使用的是Node.js 2.0版本)。本文所讲内容应该兼容所有未来的0.2.x版本。一旦编译安装完node,编译模块就不在需要额外的东西了。
完整的源代码可以在这里找到 。在使用Node.js或V8之前,我们需要包括相关的头文件:
#include <v8.h>
#include <node.h>
using namespace node;
using namespace v8;
在本例子中我直接使用了V8和node的命名空间,使代码更易于阅读。虽然这种用法和谷歌的自己的C++编程风格指南相悖,但由于你需要不停的使用V8定义的类型,所以目前为止的大多数node的扩展仍然使用了V8的命名空间。
接下来,声明HelloWorld类。它继承自node::ObjectWrap类 ,这个类提供了几个如引用计数、在V8内部传递contex等的实用功能。一般来说,所有对象应该继承ObjectWrap:
class HelloWorld: ObjectWrap
{
private:
int m_count;
public:
声明类之后,我们定义了一个静态成员函数,用来初始化对象并将其导入Node.js提供的target对象中。设个函数基本上是告诉Node.js和V8你的类是如何创建的,和它将包含什么方法:
static Persistent<FunctionTemplate> s_ct;
static void Init(Handle<Object> target)
{
HandleScope scope;
Local<FunctionTemplate> t = FunctionTemplate::New(New);
s_ct = Persistent<FunctionTemplate>::New(t);
s_ct->InstanceTemplate()->SetInternalFieldCount(1);
s_ct->SetClassName(String::NewSymbol(“HelloWorld”));
NODE_SET_PROTOTYPE_METHOD(s_ct, “hello”, Hello);
target->Set(String::NewSymbol(“HelloWorld”),
s_ct->GetFunction());
}
在上面这个函数中target参数将是模块对象,即你的扩展将要载入的地方。(译着:这个函数将你的对象及其方法连接到
这个模块对象,以便外界可以访问)首先我们为New方法创建一个FunctionTemplate,将于稍后解释。我们还为该对象添加一个内部字段,并命
名为HelloWorld。然后使用NODE_SET_PROTOTYPE_METHOD宏将hello方法绑定到该对象。最后,一旦我们建立好这个函数模板后,将他分配给target对象的HelloWorld属性,将类暴露给用户。
接下来的部分是一个标准的C++构造函数:
HelloWorld() :
m_count(0)
{
}
~HelloWorld()
{
}
接下来,在::New 方法中V8引擎将调用这个简单的C++构造函数:
static Handle<Value> New(const Arguments& args)
{
HandleScope scope;
HelloWorld* hw = new HelloWorld();
hw->Wrap(args.This());
return args.This();
}
此段代码相当于上面Javascript代码中使用的构造函数。它调用new HelloWorld
创造了一个普通的C++对象,然后调用从ObjectWrap继承的Wrap方法,
它将一个C++HelloWorld类的引用保存到args.This()的值中。在包装完成后返回args.This(),整个函数的行为和
javascript中的new运算符类似,返回this指向的对象。
现在我们已经建立了对象,下面介绍在Init函数中被绑定到hello的函数:
static Handle<Value> Hello(const Arguments& args)
{
HandleScope scope;
HelloWorld* hw = ObjectWrap::Unwrap<HelloWorld>(args.This());
hw->m_count++;
Local<String> result = String::New(“Hello World”);
return scope.Close(result);
}
函数中首先使用ObjectWrap模板的方法提取出指向HelloWorld类的指针,然后和javascript版本的HelloWorld一样递增计数器。我们新建一个内容为“HelloWorld”的v8字符串对象,然后在关闭本地作用域的时候返回这个字符串。
上面的代码实际上只是针对v8的接口,最终我们还需要让Node.js知道如何动态加载我们的代码。为了使Node.js的扩展可以在执行时从动态链接库加载,需要有一个dlsym函数可以识别的符号,所以执行编写如下代码:
extern “C” {
static void init (Handle<Object> target)
{
HelloWorld::Init(target);
}
NODE_MODULE(helloworld, init);
}
由于c++的符号命名规则,我们使用extern
C,以便该符号可以被dysym识别。init方法是Node.js加载模块后第一个调用的函数,如果你有多个类型,请全部在这里初始化。
NODE_MODULE宏用来填充一个用于存储模块信息的结构体,存储的信息如模块使用的API版本。这些信息可以用来防止未来因API不兼容导致的崩
溃。
到此,我们已经完成了一个可用的C++ NodeJS扩展。
Node.js也提供了一个用于构建模块的简单工具:
node-waf首先编写一个包含扩展编译方法的wscript文件,然后执行node-waf configure &&
node-waf build完成模块的编译和链接工作。对于这个helloworld的例子来说,wscript内容如下:
def set_options(opt):
opt.tool_options(“compiler_cxx”)
def configure(conf):
conf.check_tool(“compiler_cxx”)
conf.check_tool(“node_addon”)
def build(bld):
obj = bld.new_task_gen(“cxx”, “shlib”, “node_addon”)
obj.cxxflags = [“-g”, “-D_FILE_OFFSET_BITS=64”, “-D_LARGEFILE_SOURCE”, “-Wall”]
obj.target = “helloworld”
obj.source = “helloworld.cc”
异步IO的HelloWorld
对于实际的应用来说,HelloWorld的示例太过简单了一些,Node.js主要的优势是提供异步IO。
Node.js内部通过libeio将会产生阻塞的操作全都放入线程池中执行。如果需要和遗留的c库交互,通常需要使用异步IO来为javascript
代码提供回调接口。
通常的模式是提供一个回调,在异步操作完成时被调用——你可以在整个Node.js的API中看到这种模式。
Node.js的filesystem模块提供了一个很好的例子,其中大多数的函数都在操作完成后通过调用回调函数来传递数据。和许多传统的GUI框架一
样,Node.js只在主线程中执行JavaScript,因此主线程以外的任何操作都不应该直接和V8或Javascript交互。
同样helloworld_eio.cc源代码在GitHub上。我只强调和原来HelloWorld之间的差异,其中大部分代码保持不变,变化集中在Hello方法中:
static Handle<Value> Hello(const Arguments& args)
{
HandleScope scope;
REQ_FUN_ARG(0, cb);
HelloWorldEio* hw = ObjectWrap::Unwrap<HelloWorldEio>(args.This());
在Hello函数的入口处 ,我们使用宏从参数列表的第一个位置获取回调函数,在下一节中将详细介绍。然后,我们使用相同的Unwarp方法提取指向类对象的指针。
hello_baton_t *baton = new hello_baton_t();
baton->hw = hw;
baton->increment_by = 2;
baton->sleep_for = 1;
baton->cb = Persistent<Function>::New(cb);
这里我们创建一个baton结构,并将各种参数保存在里面。请注意,我们为回调函数创建了一个永久引用,因为我们想要在超出当前函数作用域的地方使用它。如果不这么做,在本函数结束后将无法再调用回调函数。
hw->Ref();
eio_custom(EIO_Hello, EIO_PRI_DEFAULT, EIO_AfterHello, baton);
ev_ref(EV_DEFAULT_UC);
return Undefined();
}
如下代码是真正的重点。首先,我们增加HelloWorld对象的引用计数,这样在其他线程执行的时候他就不会被回收。
函数eio_custom接受两个函数指针作为参数。EIO_Hello函数将在线程池中执行,然后EIO_AfterHello函数将回到在“主线程”
中执行。我们的baton结构也被传递进各函数,这些函数可以使用baton结构中的数据完成相关的操作。同时,我们也增加event
loop的引用。这很重要,因为如果event
loop无事可做,Node.js就会退出。最终,函数返回Undefined,因为真正的工作将在其他线程中完成。
static int EIO_Hello(eio_req *req)
{
hello_baton_t *baton = static_cast<hello_baton_t *>(req->data);
sleep(baton->sleep_for);
baton->hw->m_count += baton->increment_by;
return 0;
}
这个回调函数将在libeio管理的线程中执行。首先,解析出baton结构,这样可以访问之前设置的各种参数。然后
sheep
baton->sleep_for秒,这么做是安全的,因为这个函数运行在独立的线程中并不会阻塞主线程中javascript的执行。然后我们的
增计数器,在实际的系统中,这些操作通常需要使用Lock/Mutex进行同步。
当上述方法返回后,libeio将会通知主线程它需要在主线成上执行代码,此时EIO_AfterHello将会被调用。
static int EIO_AfterHello(eio_req *req)
{
HandleScope scope;
hello_baton_t *baton = static_cast<hello_baton_t *>(req->data);
ev_unref(EV_DEFAULT_UC);
baton->hw->Unref();
进度此函数时,我们提取出baton结构,删除事件循环的引用,并减少HelloWorld对象的引用。
Local<Value> argv[1];
argv[0] = String::New(“Hello World”);
TryCatch try_catch;
baton->cb->Call(Context::GetCurrent()->Global(), 1, argv);
if (try_catch.HasCaught()) {
FatalException(try_catch);
}
新建要传递给回调函数的字符串参数,并放入字符串数组中。然后我们调用回调传递一个参数,并检测可能抛出的异常。
baton->cb.Dispose();
delete baton;
return 0;
}
在执行过回调之后,应该销毁持久引用,然后删除之前创建的baton结构。
最后,你可以使用如下形式在Javascript中使用该模块:
var helloeio = require(‘./helloworld_eio’);
hi = new helloeio.HelloWorldEio();
hi.hello(function(data){
console.log(data);
});
参数传递与解析
除了HelloWorld之外,你还需要理解最后一个问题:参数的处理。在helloWorld EIO例子中,我们使用一个REQ_FUN_ARG宏,然我们看看这个宏到底都做些什么。
#define REQ_FUN_ARG(I, VAR) \
if (args.Length() <= (I) || !args[I]->IsFunction()) \
return ThrowException(Exception::TypeError( \
String::New(“Argument ” #I ” must be a function”))); \
Local<Function> VAR = Local<Function>::Cast(args[I]);
就像Javascript中的argument变量,v8使用数组传递所有的参数。由于没有严格的类型限制,所以传递给函数的参数数目可能和期待的不同。为了对用户友好,使用如下的宏检测一下参数数组的长度并判断参数是否是正确的类型。如果传递了错误的参数类型,该宏将会抛出TypeError异常。为简化参数的解析,目前为止大多数的Node.js扩展都有一些本地作用域内的宏,用于特定类型参数的检测。
二、揭秘node.js事件
要使用NodeJS,你需要知道一个重要的东西:事件(events)。Node中有很多对象都可以触发事件,Node
的文档中有很多示例。但文档也许并不能清晰的讲解如何编写自定义事件以及监听函数。对于一些简单的程序你可以不使用自定义事件,但这样很难应对复杂的应
用。那么如何编写自定义事件?首先需要了解的是在node.js中的’events’模块。
快速概览
要访问此模块,只需使用如下语句:
require(‘events’)
requires(‘events’).EventEmitter
特别说明,node中所有能触发事件的对象基本上都是后者的实例。让我们创建一个简单的演示程序Dummy:
mmy.js
view plain to clipboardprint?
// basic imports
var events = require(‘events’);
// for us to do a require later
mole.exports = Dummy;
function Dummy() {
events.EventEmitter.call(this);
}
10.
11. // inherit events.EventEmitter
12. Dummy.super_ = events.EventEmitter;
13. Dummy.prototype = Object.create(events.EventEmitter.prototype, {
14. constructor: {
15. value: Dummy,
16. enumerable: false
17. }
18. });
// basic imports
var events = require(‘events’);
// for us to do a require later
mole.exports = Dummy;
function Dummy() {
events.EventEmitter.call(this);
}
// inherit events.EventEmitter
Dummy.super_ = events.EventEmitter;
Dummy.prototype = Object.create(events.EventEmitter.prototype, {
constructor: {
value: Dummy,
enumerable: false
}
});
上述代码中重点展示如何使用EventEmitter扩充对象,并从中继承所有的原型对象,方法…等等。
现在,我们假设Dummy有一个cooking()的方法,一旦把食物做熟之后它会触发’cooked’事件,并调用一个名为’eat’的回调函数。
mmy-cooking.js
view plain to clipboardprint?
Dummy.prototype.cooking = function(chicken) {
var self = this;
self.chicken = chicken;
self.cook = cook(); // assume mmy function that’ll do the cooking
self.cook(chicken, function(cooked_chicken) {
self.chicken = cooked_chicken;
self.emit(‘cooked’, self.chicken);
});
10. return self;
11. }
Dummy.prototype.cooking = function(chicken) {
var self = this;
self.chicken = chicken;
self.cook = cook(); // assume mmy function that’ll do the cooking
self.cook(chicken, function(cooked_chicken) {
self.chicken = cooked_chicken;
self.emit(‘cooked’, self.chicken);
});
return self;
}
❸ Node.js 与 python 作为后端服务的编程语言各有什么优劣
一. NodeJS的特点
我们先来看看NodeJS官网上的介绍:
Node.js is a platform built on Chrome’s JavaScript runtime for easily building fast, scalable network applications. node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.
其特点为:
1. 它是一个Javascript运行环境
2. 依赖于Chrome V8引擎进行代码解释
3. 事件驱动
4. 非阻塞I/O
5. 轻量、可伸缩,适于实时数据交互应用
6. 单进程,单线程
二. NodeJS带来的对系统瓶颈的解决方案
它的出现确实能为我们解决现实当中系统瓶颈提供了新的思路和方案,下面我们看看它能解决什么问题。
1. 并发连接
举个例子,想象一个场景,我们在银行排队办理业务,我们看看下面两个模型。
(1)系统线程模型:
这种模型的问题显而易见,服务端只有一个线程,并发请求(用户)到达只能处理一个,其余的要先等待,这就是阻塞,正在享受服务的请求阻塞后面的请求了。
(2)多线程、线程池模型:
这个模型已经比上一个有所进步,它调节服务端线程的数量来提高对并发请求的接收和响应,但并发量高的时候,请求仍然需要等待,它有个更严重的问题。到代码层面上来讲,我们看看客户端请求与服务端通讯的过程:
服务端与客户端每建立一个连接,都要为这个连接分配一套配套的资源,主要体现为系统内存资源,以PHP为例,维护一个连接可能需要20M的内存。这就是为什么一般并发量一大,就需要多开服务器。
那么NodeJS是怎么解决这个问题的呢?我们来看另外一个模型,想象一下我们在快餐店点餐吃饭的场景。
(3)异步、事件驱动模型
我们同样是要发起请求,等待服务器端响应;但是与银行例子不同的是,这次我们点完餐后拿到了一个号码,拿到号码,我们往往会在位置上等待,而在我们后面的请求会继续得到处理,同样是拿了一个号码然后到一旁等待,接待员能一直进行处理。
等到饭菜做号了,会喊号码,我们拿到了自己的饭菜,进行后续的处理(吃饭)。这个喊号码的动作在NodeJS中叫做回调(Callback),能在事件(烧菜,I/O)处理完成后继续执行后面的逻辑(吃饭),这体现了NodeJS的显着特点,异步机制、事件驱动整个过程没有阻塞新用户的连接(点餐),也不需要维护已经点餐的用户与厨师的连接。
基于这样的机制,理论上陆续有用户请求连接,NodeJS都可以进行响应,因此NodeJS能支持比Java、PHP程序更高的并发量虽然维护事件队列也需要成本,再由于NodeJS是单线程,事件队列越长,得到响应的时间就越长,并发量上去还是会力不从心。
总结一下NodeJS是怎么解决并发连接这个问题的:更改连接到服务器的方式,每个连接发射(emit)一个在NodeJS引擎进程中运行的事件(Event),放进事件队列当中,而不是为每个连接生成一个新的OS线程(并为其分配一些配套内存)。
2. I/O阻塞
NodeJS解决的另外一个问题是I/O阻塞,看看这样的业务场景:需要从多个数据源拉取数据,然后进行处理。
(1)串行获取数据,这是我们一般的解决方案,以PHP为例
假如获取profile和timeline操作各需要1S,那么串行获取就需要2S。
(2)NodeJS非阻塞I/O,发射/监听事件来控制执行过程
NodeJS遇到I/O事件会创建一个线程去执行,然后主线程会继续往下执行的,因此,拿profile的动作触发一个I/O事件,马上就会执行拿timeline的动作,两个动作并行执行,假如各需要1S,那么总的时间也就是1S。它们的I/O操作执行完成后,发射一个事件,profile和timeline,事件代理接收后继续往下执行后面的逻辑,这就是NodeJS非阻塞I/O的特点。
总结一下:Java、PHP也有办法实现并行请求(子线程),但NodeJS通过回调函数(Callback)和异步机制会做得很自然。
三. NodeJS的优缺点
优点:1. 高并发(最重要的优点)
2. 适合I/O密集型应用
缺点:1. 不适合CPU密集型应用;CPU密集型应用给Node带来的挑战主要是:由于JavaScript单线程的原因,如果有长时间运行的计算(比如大循环),将会导致CPU时间片不能释放,使得后续I/O无法发起;
解决方案:分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞I/O调用的发起;
2. 只支持单核CPU,不能充分利用CPU
3. 可靠性低,一旦代码某个环节崩溃,整个系统都崩溃
原因:单进程,单线程
解决方案:(1)Nnigx反向代理,负载均衡,开多个进程,绑定多个端口;
(2)开多个进程监听同一个端口,使用cluster模块;
4. 开源组件库质量参差不齐,更新快,向下不兼容
5. Debug不方便,错误没有stack trace
四. 适合NodeJS的场景
1. RESTful API
这是NodeJS最理想的应用场景,可以处理数万条连接,本身没有太多的逻辑,只需要请求API,组织数据进行返回即可。它本质上只是从某个数据库中查找一些值并将它们组成一个响应。由于响应是少量文本,入站请求也是少量的文本,因此流量不高,一台机器甚至也可以处理最繁忙的公司的API需求。
2. 统一Web应用的UI层
目前MVC的架构,在某种意义上来说,Web开发有两个UI层,一个是在浏览器里面我们最终看到的,另一个在server端,负责生成和拼接页面。
不讨论这种架构是好是坏,但是有另外一种实践,面向服务的架构,更好的做前后端的依赖分离。如果所有的关键业务逻辑都封装成REST调用,就意味着在上层只需要考虑如何用这些REST接口构建具体的应用。那些后端程序员们根本不操心具体数据是如何从一个页面传递到另一个页面的,他们也不用管用户数据更新是通过Ajax异步获取的还是通过刷新页面。
3. 大量Ajax请求的应用
例如个性化应用,每个用户看到的页面都不一样,缓存失效,需要在页面加载的时候发起Ajax请求,NodeJS能响应大量的并发请求。总而言之,NodeJS适合运用在高并发、I/O密集、少量业务逻辑的场景。
Python的优缺点
优点
简单————Python是一种代表简单主义思想的语言。阅读一个良好的Python程序就感觉像是在读英语一样,尽管这个英语的要求非常严格!Python的这种伪代码本质是它最大的优点之一。它使你能够专注于解决问题而不是去搞明白语言本身。
易学————就如同你即将看到的一样,Python极其容易上手。前面已经提到了,Python有极其简单的语法。
免费、开源————Python是FLOSS(自由/开放源码软件)之一。简单地说,你可以自由地发布这个软件的拷贝、阅读它的源代码、对它做改动、把它的一部分用于新的自由软件中。FLOSS是基于一个团体分享知识的概念。这是为什么Python如此优秀的原因之一——它是由一群希望看到一个更加优秀的Python的人创造并经常改进着的。
高层语言————当你用Python语言编写程序的时候,你无需考虑诸如如何管理你的程序使用的内存一类的底层细节。
可移植性————由于它的开源本质,Python已经被移植在许多平台上(经过改动使它能够工作在不同平台上)。如果你小心地避免使用依赖于系统的特性,那么你的所有Python程序无需修改就可以在下述任何平台上面运行。这些平台包括Linux、Windows、FreeBSD、Macintosh、Solaris、OS/2、Amiga、AROS、AS/400、BeOS、OS/390、z/OS、Palm OS、QNX、VMS、Psion、Acom RISC OS、VxWorks、PlayStation、Sharp Zaurus、Windows CE甚至还有PocketPC、Symbian以及Google基于linux开发的Android平台!
解释性————这一点需要一些解释。一个用编译性语言比如C或C++写的程序可以从源文件(即C或C++语言)转换到一个你的计算机使用的语言(二进制代码,即0和1)。这个过程通过编译器和不同的标记、选项完成。当你运行你的程序的时候,连接/转载器软件把你的程序从硬盘复制到内存中并且运行。而Python语言写的程序不需要编译成二进制代码。你可以直接从源代码 运行 程序。在计算机内部,Python解释器把源代码转换成称为字节码的中间形式,然后再把它翻译成计算机使用的机器语言并运行。事实上,由于你不再需要担心如何编译程序,如何确保连接转载正确的库等等,所有这一切使得使用Python更加简单。由于你只需要把你的Python程序拷贝到另外一台计算机上,它就可以工作了,这也使得你的Python程序更加易于移植。
面向对象————Python既支持面向过程的编程也支持面向对象的编程。在“面向过程”的语言中,程序是由过程或仅仅是可重用代码的函数构建起来的。在“面向对象”的语言中,程序是由数据和功能组合而成的对象构建起来的。与其他主要的语言如C++和Java相比,Python以一种非常强大又简单的方式实现面向对象编程。
可扩展性————如果你需要你的一段关键代码运行得更快或者希望某些算法不公开,你可以把你的部分程序用C或C++编写,然后在你的Python程序中使用它们。
可嵌入性————你可以把Python嵌入你的C/C++程序,从而向你的程序用户提供脚本功能。
丰富的库————Python标准库确实很庞大。它可以帮助你处理各种工作,包括正则表达式、文档生成、单元测试、线程、数据库、网页浏览器、CGI、FTP、电子邮件、XML、XML-RPC、HTML、WAV文件、密码系统、GUI(图形用户界面)、Tk和其他与系统有关的操作。记住,只要安装了Python,所有这些功能都是可用的。这被称作Python的“功能齐全”理念。除了标准库以外,还有许多其他高质量的库,如wxPython、Twisted和Python图像库等等。
概括————Python确实是一种十分精彩又强大的语言。它合理地结合了高性能与使得编写程序简单有趣的特色。
规范的代码————Python采用强制缩进的方式使得代码具有极佳的可读性。
缺点
强制缩进
这也许不应该被称为局限,但是它用缩进来区分语句关系的方式还是给很多初学者带来了困惑。即便是很有经验的Python程序员,也可能陷入陷阱当中。最常见的情况是tab和空格的混用会导致错误,而这是用肉眼无法分别的。
单行语句和命令行输出问题
很多时候不能将程序连写成一行,如import sys;for i in sys.path:print i。而perl和awk就无此限制,可以较为方便的在shell下完成简单程序,不需要如Python一样,必须将程序写入一个.py文件。(对很多用户而言这也不算是限制)
NO.1 运行速度,有速度要求的话,用C++改写关键部分吧。
NO.2 国内市场较小(国内以python来做主要开发的,目前只有一些 web2.0公司)。但时间推移,目前很多国内软件公司,尤其是游戏公司,也开始规模使用他。
No.3 中文资料匮乏(好的python中文资料屈指可数)。托社区的福,有几本优秀的教材已经被翻译了,但入门级教材多,高级内容还是只能看英语版。
NO.4 构架选择太多(没有像C#这样的官方.net构架,也没有像ruby由于历史较短,构架开发的相对集中。Ruby on Rails 构架开发中小型web程序天下无敌)。不过这也从另一个侧面说明,python比较优秀,吸引的人才多,项目也多。
❹ Nodejs编程md5怎么计算
文件:
var filename = process.argv[2];
var crypto = require('crypto');
var fs = require('fs');
var md5sum = crypto.createHash('md5');
var s = fs.ReadStream(filename);
s.on('data', function(d) {
md5sum.update(d);
});
s.on('end', function() {
var d = md5sum.digest('hex');
console.log(d + ' ' + filename);
});
字串:
var crypto = require('crypto');
var hash = crypto.createHash('md5').update('AAA').digest("hex");
console.log(hash);