• 关于

    函数编程语言干什么用的

    的搜索结果

回答

来源:掘金 不会写伪代码 伪代码是什么呢?就是自然语言啊。其实编程只有三种逻辑控制块,顺序,循环,判断。所以你只要用自然语言来描述出来,先做什么,再做什么,什么时候循环,什么时候判断,代码写出来的问题就不大。这是一个先写伪代码再写细节的过程。你不要上来就开始平铺写代码。 平铺代码是最菜的方式,好的代码是有结构的,有不同的抽像层级。 第一步,干嘛。 第二步,干嘛。 第三步,干嘛。 先把这个列清楚,这是伪代码的第一级。 然后变成注释,这是第二级。 删掉注释变成函数名,这是第三级。 所以说,**好的程序员写代码是不需要注释的,不是说让你把注释删掉,而是让你完成这三步升华的过程。**写的好的代码,命名规范,你看到的真的是一首诗, 是一种编程语言,是在用语言来描述一件功能的完成,这种编程艺术的工业感很爽快,你看那些不爽的代码,简直了。一步一个坑: 不做数据量的预估 后端工程师在前期经常会忽视数据量的大小,没有影成一个好的习惯。写代码只注重功能,没有一个关于数据量的概念。这个地方其实还和性能是一致的,在性能上,前后端并没有太大的差别。推荐的做法是,程序员要对数据很敏感,后端要知道每一个表的规模可能会有多大,当前的系统能支持的数据库表的大小是多大,而前后端都需要知道每一个操作,都分成了哪几个步骤,每一个步骤花费的时间是多少,大概占用的内存是什么样的。做到这一点其实并不难,难的是养成这种习惯,初级工程师眼里看的是功能和代码,中级工程师眼里看到的是数据和时间。没有预估,最后起火了,往往是这样的:

茶什i 2019-12-20 17:39:48 0 浏览量 回答数 0

问题

2016年JavaScript开发者需要了解的技能

技术小菜鸟 2019-12-01 21:34:00 3141 浏览量 回答数 1

回答

Python 的 Decorator在使用上和Java/C#的Annotation很相似,就是在方法名前面加一个@XXX注解来为这个方法装饰一些东西。但是,Java/C#的Annotation也很让人望而却步,太TMD的复杂了,你要玩它,你需要了解一堆Annotation的类库文档,让人感觉就是在学另外一门语言。 而Python使用了一种相对于Decorator Pattern和Annotation来说非常优雅的方法,这种方法不需要你去掌握什么复杂的OO模型或是Annotation的各种类库规定,完全就是语言层面的玩法:一种函数式编程的技巧。如果你看过本站的《函数式编程》,你一定会为函数式编程的那种“描述你想干什么,而不是描述你要怎么去实现”的编程方式感到畅快。(如果你不了解函数式编程,那在读本文之前,还请你移步去看看《函数式编程》) 好了,我们先来点感性认识,看一个Python修饰器的Hello World的代码。 Hello World 下面是代码:文件名:hello.py def hello(fn): def wrapper(): print "hello, %s" % fn.__name__ fn() print "goodby, %s" % fn.__name__ return wrapper @hellodef foo(): print "i am foo" foo() 当你运行代码,你会看到如下输出: [chenaho@chenhao-air]$ python hello.pyhello, fooi am foogoodby, foo 你可以看到如下的东西: 1)函数foo前面有个@hello的“注解”,hello就是我们前面定义的函数hello 2)在hello函数中,其需要一个fn的参数(这就用来做回调的函数) 3)hello函数中返回了一个inner函数wrapper,这个wrapper函数回调了传进来的fn,并在回调前后加了两条语句。 Decorator 的本质 对于Python的这个@注解语法糖- Syntactic Sugar 来说,当你在用某个@decorator来修饰某个函数func时,如下所示: @decoratordef func(): pass 其解释器会解释成下面这样的语句: func = decorator(func) 尼玛,这不就是把一个函数当参数传到另一个函数中,然后再回调吗?是的,但是,我们需要注意,那里还有一个赋值语句,把decorator这个函数的返回值赋值回了原来的func。 根据《函数式编程》中的first class functions中的定义的,你可以把函数当成变量来使用,所以,decorator必需得返回了一个函数出来给func,这就是所谓的higher order function 高阶函数,不然,后面当func()调用的时候就会出错。 就我们上面那个hello.py里的例子来说, @hellodef foo(): print "i am foo" 被解释成了: foo = hello(foo) 是的,这是一条语句,而且还被执行了。你如果不信的话,你可以写这样的程序来试试看: def fuck(fn): print "fuck %s!" % fn.__name__[::-1].upper() @fuckdef wfg(): pass 没了,就上面这段代码,没有调用wfg()的语句,你会发现, fuck函数被调用了,而且还很NB地输出了我们每个人的心声! 再回到我们hello.py的那个例子,我们可以看到,hello(foo)返回了wrapper()函数,所以,foo其实变成了wrapper的一个变量,而后面的foo()执行其实变成了wrapper()。 知道这点本质,当你看到有多个decorator或是带参数的decorator,你也就不会害怕了。 比如:多个decorator @decorator_one@decorator_twodef func(): pass 相当于: func = decorator_one(decorator_two(func)) 比如:带参数的decorator: @decorator(arg1, arg2)def func(): pass 相当于: func = decorator(arg1,arg2)(func) 这意味着decorator(arg1, arg2)这个函数需要返回一个“真正的decorator”。 带参数及多个Decrorator 我们来看一个有点意义的例子:html.py def makeHtmlTag(tag, args, *kwds): def real_decorator(fn): css_class = " class='{0}'".format(kwds["css_class"]) if "css_class" in kwds else "" def wrapped(*args, **kwds): return "<"+tag+css_class+">" + fn(*args, **kwds) + "</"+tag+">" return wrapped return real_decorator @makeHtmlTag(tag="b", css_class="bold_css")@makeHtmlTag(tag="i", css_class="italic_css")def hello(): return "hello world" print hello() 输出: hello world 在上面这个例子中,我们可以看到:makeHtmlTag有两个参数。所以,为了让 hello = makeHtmlTag(arg1, arg2)(hello) 成功,makeHtmlTag 必需返回一个decorator(这就是为什么我们在makeHtmlTag中加入了real_decorator()的原因),这样一来,我们就可以进入到 decorator 的逻辑中去了—— decorator得返回一个wrapper,wrapper里回调hello。看似那个makeHtmlTag() 写得层层叠叠,但是,已经了解了本质的我们觉得写得很自然。 你看,Python的Decorator就是这么简单,没有什么复杂的东西,你也不需要了解过多的东西,使用起来就是那么自然、体贴、干爽、透气,独有的速效凹道和完美的吸收轨迹,让你再也不用为每个月的那几天感到焦虑和不安,再加上贴心的护翼设计,量多也不用当心。对不起,我调皮了。 什么,你觉得上面那个带参数的Decorator的函数嵌套太多了,你受不了。好吧,没事,我们看看下面的方法。 class式的 Decorator 首先,先得说一下,decorator的class方式,还是看个示例: class myDecorator(object): def __init__(self, fn): print "inside myDecorator.__init__()" self.fn = fn def __call__(self): self.fn() print "inside myDecorator.__call__()" @myDecoratordef aFunction(): print "inside aFunction()" print "Finished decorating aFunction()" aFunction() 输出: inside myDecorator.__init__() Finished decorating aFunction() inside aFunction() inside myDecorator.__call__() 上面这个示例展示了,用类的方式声明一个decorator。我们可以看到这个类中有两个成员:1)一个是__init__(),这个方法是在我们给某个函数decorator时被调用,所以,需要有一个fn的参数,也就是被decorator的函数。2)一个是__call__(),这个方法是在我们调用被decorator函数时被调用的。上面输出可以看到整个程序的执行顺序。 这看上去要比“函数式”的方式更易读一些。 下面,我们来看看用类的方式来重写上面的html.py的代码:html.py class makeHtmlTagClass(object): def __init__(self, tag, css_class=""): self._tag = tag self._css_class = " class='{0}'".format(css_class) if css_class !="" else "" def __call__(self, fn): def wrapped(*args, **kwargs): return "<" + self._tag + self._css_class+">" + fn(*args, **kwargs) + "</" + self._tag + ">" return wrapped @makeHtmlTagClass(tag="b", css_class="bold_css")@makeHtmlTagClass(tag="i", css_class="italic_css")def hello(name): return "Hello, {}".format(name) print hello("Hao Chen") 上面这段代码中,我们需要注意这几点:1)如果decorator有参数的话,__init__() 成员就不能传入fn了,而fn是在__call__的时候传入的。2)这段代码还展示了 wrapped(args, *kwargs) 这种方式来传递被decorator函数的参数。(其中:args是一个参数列表,kwargs是参数dict,具体的细节,请参考Python的文档或是StackOverflow的这个问题,这里就不展开了) 用Decorator设置函数的调用参数 你有三种方法可以干这个事: 第一种,通过 **kwargs,这种方法decorator会在kwargs中注入参数。 def decorate_A(function): def wrap_function(*args, **kwargs): kwargs['str'] = 'Hello!' return function(*args, **kwargs) return wrap_function @decorate_Adef print_message_A(args, *kwargs): print(kwargs['str']) print_message_A() 第二种,约定好参数,直接修改参数 def decorate_B(function): def wrap_function(*args, **kwargs): str = 'Hello!' return function(str, *args, **kwargs) return wrap_function @decorate_Bdef print_message_B(str, args, *kwargs): print(str) print_message_B() 第三种,通过 *args 注入 def decorate_C(function): def wrap_function(*args, **kwargs): str = 'Hello!' #args.insert(1, str) args = args +(str,) return function(*args, **kwargs) return wrap_function class Printer: @decorate_C def print_message(self, str, *args, **kwargs): print(str) p = Printer()p.print_message() Decorator的副作用 到这里,我相信你应该了解了整个Python的decorator的原理了。 相信你也会发现,被decorator的函数其实已经是另外一个函数了,对于最前面那个hello.py的例子来说,如果你查询一下foo.__name__的话,你会发现其输出的是“wrapper”,而不是我们期望的“foo”,这会给我们的程序埋一些坑。所以,Python的functool包中提供了一个叫wrap的decorator来消除这样的副作用。下面是我们新版本的hello.py。文件名:hello.py from functools import wrapsdef hello(fn): @wraps(fn) def wrapper(): print "hello, %s" % fn.__name__ fn() print "goodby, %s" % fn.__name__ return wrapper @hellodef foo(): '''foo help doc''' print "i am foo" pass foo()print foo.__name__ #输出 fooprint foo.__doc__ #输出 foo help doc 当然,即使是你用了functools的wraps,也不能完全消除这样的副作用。 来看下面这个示例: from inspect import getmembers, getargspecfrom functools import wraps def wraps_decorator(f): @wraps(f) def wraps_wrapper(*args, **kwargs): return f(*args, **kwargs) return wraps_wrapper class SomeClass(object): @wraps_decorator def method(self, x, y): pass obj = SomeClass()for name, func in getmembers(obj, predicate=inspect.ismethod): print "Member Name: %s" % name print "Func Name: %s" % func.func_name print "Args: %s" % getargspec(func)[0] 输出: Member Name: method Func Name: method Args: [] 你会发现,即使是你你用了functools的wraps,你在用getargspec时,参数也不见了。 要修正这一问,我们还得用Python的反射来解决,下面是相关的代码: def get_true_argspec(method): argspec = inspect.getargspec(method) args = argspec[0] if args and args[0] == 'self': return argspec if hasattr(method, '__func__'): method = method.__func__ if not hasattr(method, 'func_closure') or method.func_closure is None: raise Exception("No closure for method.") method = method.func_closure[0].cell_contents return get_true_argspec(method) 当然,我相信大多数人的程序都不会去getargspec。所以,用functools的wraps应该够用了。 一些decorator的示例 好了,现在我们来看一下各种decorator的例子: 给函数调用做缓存 这个例实在是太经典了,整个网上都用这个例子做decorator的经典范例,因为太经典了,所以,我这篇文章也不能免俗。 from functools import wrapsdef memo(fn): cache = {} miss = object() @wraps(fn) def wrapper(*args): result = cache.get(args, miss) if result is miss: result = fn(*args) cache[args] = result return result return wrapper @memodef fib(n): if n < 2: return n return fib(n - 1) + fib(n - 2) 上面这个例子中,是一个斐波拉契数例的递归算法。我们知道,这个递归是相当没有效率的,因为会重复调用。比如:我们要计算fib(5),于是其分解成fib(4) + fib(3),而fib(4)分解成fib(3)+fib(2),fib(3)又分解成fib(2)+fib(1)…… 你可看到,基本上来说,fib(3), fib(2), fib(1)在整个递归过程中被调用了两次。 而我们用decorator,在调用函数前查询一下缓存,如果没有才调用了,有了就从缓存中返回值。一下子,这个递归从二叉树式的递归成了线性的递归。 Profiler的例子 这个例子没什么高深的,就是实用一些。 import cProfile, pstats, StringIO def profiler(func): def wrapper(*args, **kwargs): datafn = func.__name__ + ".profile" # Name the data file prof = cProfile.Profile() retval = prof.runcall(func, *args, **kwargs) #prof.dump_stats(datafn) s = StringIO.StringIO() sortby = 'cumulative' ps = pstats.Stats(prof, stream=s).sort_stats(sortby) ps.print_stats() print s.getvalue() return retval return wrapper 注册回调函数 下面这个示例展示了通过URL的路由来调用相关注册的函数示例: class MyApp(): def __init__(self): self.func_map = {} def register(self, name): def func_wrapper(func): self.func_map[name] = func return func return func_wrapper def call_method(self, name=None): func = self.func_map.get(name, None) if func is None: raise Exception("No function registered against - " + str(name)) return func() app = MyApp() @app.register('/')def main_page_func(): return "This is the main page." @app.register('/next_page')def next_page_func(): return "This is the next page." print app.call_method('/')print app.call_method('/next_page') 注意:1)上面这个示例中,用类的实例来做decorator。2)decorator类中没有__call__(),但是wrapper返回了原函数。所以,原函数没有发生任何变化。 给函数打日志 下面这个示例演示了一个logger的decorator,这个decorator输出了函数名,参数,返回值,和运行时间。 from functools import wrapsdef logger(fn): @wraps(fn) def wrapper(*args, **kwargs): ts = time.time() result = fn(*args, **kwargs) te = time.time() print "function = {0}".format(fn.__name__) print " arguments = {0} {1}".format(args, kwargs) print " return = {0}".format(result) print " time = %.6f sec" % (te-ts) return result return wrapper @loggerdef multipy(x, y): return x * y @loggerdef sum_num(n): s = 0 for i in xrange(n+1): s += i return s print multipy(2, 10)print sum_num(100)print sum_num(10000000) 上面那个打日志还是有点粗糙,让我们看一个更好一点的(带log level参数的): import inspectdef get_line_number(): return inspect.currentframe().f_back.f_back.f_lineno def logger(loglevel): def log_decorator(fn): @wraps(fn) def wrapper(*args, **kwargs): ts = time.time() result = fn(*args, **kwargs) te = time.time() print "function = " + fn.__name__, print " arguments = {0} {1}".format(args, kwargs) print " return = {0}".format(result) print " time = %.6f sec" % (te-ts) if (loglevel == 'debug'): print " called_from_line : " + str(get_line_number()) return result return wrapper return log_decorator 但是,上面这个带log level参数的有两具不好的地方,1) loglevel不是debug的时候,还是要计算函数调用的时间。2) 不同level的要写在一起,不易读。 我们再接着改进: import inspect def advance_logger(loglevel): def get_line_number(): return inspect.currentframe().f_back.f_back.f_lineno def _basic_log(fn, result, *args, **kwargs): print "function = " + fn.__name__, print " arguments = {0} {1}".format(args, kwargs) print " return = {0}".format(result) def info_log_decorator(fn): @wraps(fn) def wrapper(*args, **kwargs): result = fn(*args, **kwargs) _basic_log(fn, result, args, kwargs) return wrapper def debug_log_decorator(fn): @wraps(fn) def wrapper(*args, **kwargs): ts = time.time() result = fn(*args, **kwargs) te = time.time() _basic_log(fn, result, args, kwargs) print " time = %.6f sec" % (te-ts) print " called_from_line : " + str(get_line_number()) return wrapper if loglevel is "debug": return debug_log_decorator else: return info_log_decorator 你可以看到两点,1)我们分了两个log level,一个是info的,一个是debug的,然后我们在外尾根据不同的参数返回不同的decorator。2)我们把info和debug中的相同的代码抽到了一个叫_basic_log的函数里,DRY原则。 一个MySQL的Decorator 下面这个decorator是我在工作中用到的代码,我简化了一下,把DB连接池的代码去掉了,这样能简单点,方便阅读。 import umysqlfrom functools import wraps class Configuraion: def __init__(self, env): if env == "Prod": self.host = "coolshell.cn" self.port = 3306 self.db = "coolshell" self.user = "coolshell" self.passwd = "fuckgfw" elif env == "Test": self.host = 'localhost' self.port = 3300 self.user = 'coolshell' self.db = 'coolshell' self.passwd = 'fuckgfw' def mysql(sql): _conf = Configuraion(env="Prod") def on_sql_error(err): print err sys.exit(-1) def handle_sql_result(rs): if rs.rows > 0: fieldnames = [f[0] for f in rs.fields] return [dict(zip(fieldnames, r)) for r in rs.rows] else: return [] def decorator(fn): @wraps(fn) def wrapper(*args, **kwargs): mysqlconn = umysql.Connection() mysqlconn.settimeout(5) mysqlconn.connect(_conf.host, _conf.port, _conf.user, _conf.passwd, _conf.db, True, 'utf8') try: rs = mysqlconn.query(sql, {}) except umysql.Error as e: on_sql_error(e) data = handle_sql_result(rs) kwargs["data"] = data result = fn(*args, **kwargs) mysqlconn.close() return result return wrapper return decorator @mysql(sql = "select * from coolshell" )def get_coolshell(data): ... ... ... .. 线程异步 下面量个非常简单的异步执行的decorator,注意,异步处理并不简单,下面只是一个示例。 from threading import Threadfrom functools import wraps def async(func): @wraps(func) def async_func(*args, **kwargs): func_hl = Thread(target = func, args = args, kwargs = kwargs) func_hl.start() return func_hl return async_func if name == '__main__': from time import sleep @async def print_somedata(): print 'starting print_somedata' sleep(2) print 'print_somedata: 2 sec passed' sleep(2) print 'print_somedata: 2 sec passed' sleep(2) print 'finished print_somedata' def main(): print_somedata() print 'back in main' print_somedata() print 'back in main' main() 其它 关于更多的示例,你可以参看: Python Decorator Library来源:网络

51干警网 2019-12-02 01:10:47 0 浏览量 回答数 0

阿里云试用中心,为您提供0门槛上云实践机会!

0元试用32+款产品,最高免费12个月!拨打95187-1,咨询专业上云建议!

问题

关于代码注释我的个人看法:报错

kun坤 2020-06-09 11:22:00 0 浏览量 回答数 1

问题

【精品问答】python技术1000问(1)

问问小秘 2019-12-01 21:57:48 454222 浏览量 回答数 19

回答

虽然我不是Python高手,但我是零基础,之前会的都是软件PS,PPT之类。点击链接加入群【我爱python大神】:https://jq.qq.com/?_wv=1027&k=47zuLPd 如果目的是想成为程序员,参考教学大纲。 如果只是学程序,理解科技,解决工作问题,我的方式可以参考使用: 1,找到合适的入门书籍,大致读一次,循环啊判断啊,常用类啊,搞懂(太难的跳过) 2,做些简单习题,字符串比较,读取日期之类PythonCookbook不错(太难太无趣的,再次跳过,保持兴趣是最重要的,不会的以后可以再学) 3,加入Python讨论群,态度友好笑眯眯(很重要,这样高手才会耐心纠正你错误常识)。很多小问题,纠结许久,对方一句话点播思路,真的节约你很多时间。耐心指教我的好人,超级超级多谢。 4,解决自己电脑问题。比如下载美剧,零散下载了2,4,5,8集,而美剧共12集,怎样找出漏下的那几集?然后问题分解,1读取全部下载文件名,2提取集的数字,3数字排序和(1--12)对比,找出漏下的。点击链接加入群【我爱python大神】:https://jq.qq.com/?_wv=1027&k=47zuLPd 5,时刻记住目的,不是为了当程序员,是为了解决问题。比如,想偷懒抓网页内容,用urllib不行,用request也不行,才发现抓取内容涉及那么多方面(cookie,header,SSL,url,javascript等等),当然可以听人家劝,回去好好读书,从头读。 或者,不求效率,只求解决,用ie打开网页再另存为行不行?ie已经渲染过全部结果了。 问题变成:1--打开指定的10个网页(一行代码就行)。更复杂的想保存呢?利用已经存在的包,比如PAM30(我的是Python3),直接打开ie,用函数outHTML另存为文本,再用搜索函数(str搜索也行,re正则也行)找到数据。简单吧?而且代码超级短。 6,保持兴趣,用最简单的方式解决问题,什么底层驱动,各种交换,留给大牛去写吧。我们利用已经有的包完成。 7,耐心读文档,并且练习快速读文档。拿到新包,找到自己所需要的函数,是需要快速读一次的。这个不难,读函数名,大概能猜到是干嘛的,然后看看返回值,能判断是不是自己需要的。 8,写帮助文件和学习笔记,并发布共享。教别人的时候,其实你已经自己再次思考一次了。 我觉得学程序就像学英文,把高频率的词(循环,判断,常用包,常用函数)搞懂,就能拼装成自己想要的软件。 然后点点击链接加入群【我爱python大神】:https://jq.qq.com/?_wv=1027&k=47zuLPd是很好用的。 然后,坚持下去~ 6月10日补充------------------------------ 一定要保持兴趣,太复杂的跳过,就像小学数学,小学英语,都是由简入深。 网络很平面,无数国际大牛著作好书,关于Python,算法,电脑,网络,或者程序员思路,或者商业思维(浪潮之巅是本好书)等等,还有国际名校的网络公开课(中英文字幕翻译完毕,观看不是难事),讲计算机,网络,安全,或者安卓系统,什么都有,只要能持续保持兴趣,一点点学习下去,不是难事。 所有天才程序员,都曾是儿童,回到儿童思维来理解和学习。觉得什么有趣,先学,不懂的,先放着,遇到问题再来学,效果更好。 唯一建议是,不要太贪心,耐心学好一门优雅的语言,再学其它。虽然Javascript做特效很炫,或提某问题时,有大牛建议,用Ruby来写更好之类,不要改方向。就像老笑话:“要学习递归,必须首先理解递归。”然后死循环一直下去。坚持学好一门语言,再研究其他。 即使一门语言,跟网络,数据库等等相关的部分,若都能学好,再学其他语言,是很快的事情。 另外就是,用学英文的耐心来学计算机,英文遇到不懂的词,抄下,查询。 python里,看到Http,查查定义,看到outHtml,查查定义,跟初学英语时候一样,不要直接猜意思,因为精确描述性定义,跟含糊自然语有区别的。而新人瞎猜,很容易错误理解,wiki,google很有用。 我还在使劲啃Python的路上~~一起加油:) 2012年8月26日补充线------------------------------------------------------------------ QQ群:22507237陆续有些高手走了,也有新人加入。 另外10月20日,上海有Python开发者大会, 给出2个截图吧,我最近做的,真的很烂,但是能用:) 这个是上次Python测试题目“从电商网站的搜索页中抓取制作商品图片墙”。我选了最最容易的静态网站。当然京东的抓取,比这种难。 这个很方便我自己每天查询,用Python3+PyQt4,用“公司名字”关键词,在各个论坛,图片,视频,商场查询。每天看一次,很方便快速了解信息。 1.如果是因为兴趣,想做些比较漂亮的网页或者做些特别的、能帮到自己的小程序,可以直接买市面上的大部分Python教材,直接从Python学起,学实际的编程。Python并不难学,最初设计的时候就力图规避一些C、C++等等程序让入门者头大的内容,而且库函数也比较丰富,语法相对清晰直白,不会故意做一些高效率但是难弄懂的东西。而且相对语法要求(尤其是缩进==)比较严比较死,虽然你会觉得麻烦,不过确实易读而且省的粗心犯错。 2.如果是想从事编程的职业,建议还是循序渐进的来,单纯只学语言比较浅,还是从数据结构、离散数学、算法一步一步来比较好。这样学确实很枯燥,但是基础比较好,可塑性强些,再学其他算法和语言都方便不少,而且读好的源码理解的更透更深。真正专业性的学习和兴趣式的尝试差别还是很大的,要真的非常感兴趣肯吃苦才行,虽然经常看到有很多人在报考或者转入这方面的专业,不过说实话急着跳出去的一样不少。 实际上,要把一段代码编程直观的产品、工具,远远没有你想像的那么难,与其他东西的学习一样都是模仿加重复性练习,不过是非专业的人接触的少所以觉得编程特别难。现在编程语言和工具越来越多,发展很快,编程的门槛已经降低了很多了。只是相对来说,精通很难,非常难。。。 我的朋友问我怎么能快速地掌握Python。我想Python包含的内容很多,加上各种标准库,拓展库,乱花渐欲迷人眼,就想写一个快速的,类似于w3cschool风格的Python教程,一方面保持言语的简洁,另一方面循序渐进,尽量让没有背景的读者也可以从基础开始学习。另外,我在每一篇中专注于一个小的概念,希望可以让人在闲暇时很快读完。?  学好python你需要一个良好的环境,一个优质的开发交流群,群里都是那种相互帮助的人才是可以的,我有建立一个python学习交流群,在群里我们相互帮助,相互关心,相互分享内容,这样出问题帮助你的人就比较多,群号是304加上050最後799,这样就可以找到大神聚合的群,如果你只愿意别人帮助你,不愿意分享或者帮助别人,那就请不要加了,你把你会的告诉别人这是一种分享。 感觉写的好,对你有帮助,就点个赞呗,别光只收藏哈.~( ̄▽ ̄)~ ?

爱吃鱼的程序员 2020-06-08 17:59:21 0 浏览量 回答数 0

问题

【python学习全家桶】263道python热门问题,阿里百位技术专家答疑解惑

管理贝贝 2019-12-01 20:07:21 7217 浏览量 回答数 2

问题

第6篇 指针数组字符串(下):报错

kun坤 2020-06-08 11:01:44 4 浏览量 回答数 1

问题

【Java学习全家桶】1460道Java热门问题,阿里百位技术专家答疑解惑

管理贝贝 2019-12-01 20:07:15 27612 浏览量 回答数 19

问题

【精品问答】Python二级考试题库

珍宝珠 2019-12-01 22:03:38 1146 浏览量 回答数 2

回答

以下是我见过笑点比较高的: 1、 有看过这部剧的吗?推荐一下:《黑客军团》(Mr. Robot) 2、A man and woman are in a computer programming lecture. The man touches the woman's breasts. "Hey!" she says. "Those are private!" The man says, "But we're in the same class!" From Quora: 3、50 shades of Grey(五十度灰)讲的是什么: #272727, #282828, #292929, #2b2b2b, #2c2c2c, #2e2e2e, #313131, #323232, #343434, #353535, #373737, #393939, #3a3a3a, #3c3c3c, #3f3f3f, #404040, #424242, #444444, #454545, #474747, #484848, #4a4a4a, #4b4b4b, #4d4d4d, #4e4e4e, #505050, #515151, #535353, #565656, #575757, #585858, #595959, #5b5b5b, #5c5c5c, #5e5e5e, #616161, #626262, #646464, #656565, #676767, #6a6a6a, #6b6b6b, #6c6c6c, #6d6d6d, #6f6f6f, #727272, #737373, #757575, #767676, #777777, #7b7b7b, #7c7c7c, #7d7d7d, #7e7e7e, #808080, #818181, #838383, #868686, #878787, #888888, #898989, #8b8b8b, #8c8c8c, #8e8e8e, #919191, #929292, #949494, #959595, #979797, #9a9a9a, #9b9b9b, #9c9c9c, #9d9d9d, #9f9f9f, #a0a0a0, #a2a2a2, #a5a5a5, #a6a6a6, #a8a8a8. 4、 5、一程序员去面试,面试官问:“你毕业才两年,这三年工作经验是怎么来的?!” 程序员答:“加班。” 6、女朋友对着正在写代码的程序猿男朋友说:你又在写bug啦? 7、《c++程序设计语言》比《c程序设计语言》厚了几倍...果然有了对象就麻烦很多... 8、问:如何在Linux下生成随机串? 答:让新手退出Vim。 9、上大学那会,刚学会上网,于是在网上搜A片,然后搜出个:PHP大全.rmvb,以为是拍黄片大全,谁知道竟然是PHP的视频教程,于是我就学会了PHP……(╯-╰)/ 10、一对程序员情侣在一起的时候干什么? 答:面向对象编程。 11、问:怎么使用面向对象的方式变得富有? 答:继承。 12、程序猿的必读书籍: 第一阶段:《C语言程序与设计》《c++进阶宝典》《Swift入门与实践》 第二阶段:《教你怎么不生气》《老子》《沉默的愤怒》 第三阶段:《女装指南》 第四阶段:《颈椎病康复指南》《腰椎间盘突出日常护理》《强迫症的自我恢复》 第五阶段:《活着》 13、一个女程序员twitter上发了一条tweet: 昨晚梦见男朋友和别的女人在逛街,梦里我的第一反应是查源代码…结果调试半天查不出来为什么显示的是那个女人不是我,最后含泪把那个女人给注释掉了,再一运行就是我男朋友自己逛街了…醒来囧字脸呆了很久…囧rz 网友评论: 1、把那个女人的指针指向你即可 2、谁让你把男朋友设成public的? 3、加个断点看看那女人是谁 4、心真软,就应该把他的接口屏蔽掉 5、Protected逛街(youOnly) 6、设计问题,应该采用单例模式 7、没做回归测试 8、标准做法是做个断言 9、注释掉了,逛街的参数不用改吗? 10、最后含泪把那个女人给注释掉了,再一运行就是我男朋友自己逛街了-->很明显是变量名作用域的问题,改个名就行了 11、还可以有个多线程的算法,把你的优先级设成99,一个idle线程的优先级设成50,把那个女人的优先级设成49。酱紫就永远都调度不到啦 12、那也没关系,那就老调用那个女人。。。你BF放在那里不动。。。养着 13、上绝招,用goto,做个死循环,让他们逛死 14、善心点,别goto了,调用exit函数结束进程吧,冤冤相报何时了啊 15、查一下Log,仅仅只有逛街吗? 14、为什么程序员总是搞混万圣节和圣诞节? 因为 Oct 31 = Dec 25。(Oct既是十月October缩写,也是八进制Octal的缩写;Dec既是十二月December的缩写,也是十进制Decimal的缩写。八进制的31和十进制的25相等。) 15、某猿退休后决定练习书法,于是重金购买文房四宝。一日,饭后突生雅兴,一番研墨拟纸,并点上上好檀香。定神片刻,泼墨挥毫,郑重地写下一行字:hello world! 16、面试官:知道什么叫类么? 应聘者:我这人实在,工作努力,不知道什么叫累。 面试官:知道什么是包? 应聘者:我这人实在 平常不带包 也不用公司准备了。 面试官:知道什么是接口吗? 应聘者:我这个人工作认真。从来不找借口偷懒。 面试官:知道什么是继承么? 应聘者:我是孤儿没什么可以继承的。 面试官:知道什么叫对象么? 应聘者:知道,不过我工作努力,上进心强,暂时还没有打算找对象。 面试官:知道多态么? 应聘者:知道,我很保守的。我认为让心爱的女人为了自已一时的快乐去堕胎是不道德的行为!请问这和C#有什么关系?? 17、 18、 你是哪一种? 19、 Tab or Space? 最后,我想说,年轻人你渴望力量吗?

有只黑白猫 2020-01-08 14:15:01 0 浏览量 回答数 0

回答

首先,不论是PHP还是JS都不能修改客户端的文件。 你可以在客户端用JS修改XML数据,注意是数据,再传到服务器端用PHP保存成文档。######+1,网页不能允许你修改客户本地内容,得到数据然后后台根据这些数据再去读写服务器上的内容######我可以用js操作vba修改我本地的office文档,这是怎么回事######意识是不管xml放在服务器里面还是我本地的e盘里都不能修改吧?######回复 @業餘碼農 : 映射可能不准确,应该是理解成副本要好点。######回复 @業餘碼農 : 这两天脑壳想了很多。个人理解成,每个用户在处理php等的时候是获取其文档里面的一个映射,然后再处理。你说的fclose,我理解成很多用户在一个服务器里面映射了很多php文档,如果不关闭,每个映射在处理过程中都占用一定内存,但是~!~,如果没个用户使用映射的时间不一样,那么对于fclose就可有可无,因为反正用户使用映射完了传送数据给用户了,打开的文档就自动关闭,是把?######回复 @kog-7 : 而unset,不一定是用来销毁数组的。 也可以用来销毁数组元素的。比如unset( $arr['a'] ); 这样就是纯粹的数组函数了。 关于PHP事件,不知道可不可以这样称呼, PHP只有一种事件,就是请求事件,就是说只有客户端请求它才会响应并执行。 当然如果你在服务器设置了计划任务那就另当别论了。 以上都是我的个人观点。经验之谈。 不一定正确。######回复 @kog-7 : fclose你可能现在看不出作用。 但是大项目的时候,资源优化要做的很全面的。 一个用户读一个文件是1M,1000个用户同时读就是1G,并且占用1000个I/O资源,用完就手动fclose,而不是等到程序结束,这样就能在同一时刻减少I/O占用率( 有时你看到fclose靠近文件末尾,但那里有时并不代表程序结束。特别是面向对象程序设计 )。######回复 @業餘碼農 : 就是点击,或者某个状态生成了激活某处功能。###### 引用来自“kog-7”的答案 我可以用js操作vba修改我本地的office文档,这是怎么回事 百度了一下 : Visual Basic for Applications(VBA)是Visual Basic的一种宏语言,主要能用来扩展Windows的应用程式功能,特别是Microsoft Office软件。也可说是一种应用程式视觉化的Basic Script。 关键是你能修改别的文档吗? ###### 引用来自“kog-7”的答案 意识是不管xml放在服务器里面还是我本地的e盘里都不能修改吧?  。。呃,关键不在于内存的占用。 而在于I/O的占用。 内存很便宜,但是I/O资源有限,你要知道像百度谷歌这样的大网站,每秒钟都会有几千上万的用户在同时操作。而且一个请求不是一秒就可以完成的。 虽说现在有什么负载均衡的技术,不过算下来,每时段的用户请求也不是小数目 。fclose要养成习惯。数据库也是一样。 遇到大项目就不易出问题。 你说的映射,或者副本,应该可以理解成C语言里的指针。 你可以想象一下,如果某个用户上传了一个100G的文件,如果要删除这个文件,是不是要把它载入内存? 我想不可能吧。  读取也是一样, 通过指针去读取数据流而已。 而不用把整个文件放入内存。 并且单个用户的内存占用是有限制的。所以fclose是省I/O。 ######如果没经过内存的,再要引用他,就要指定相关已被传输的文档,然后找起!!!是不? (限制字数,我分开回答)######同时我理解的js和html也如此,也是向文档请求,然后文档把其代码复制张贴到内存。。。这样子我觉得要容易理解一些,也很容易解释为什么你操作的js是不会反应到本来的js文档中的。。。。同时对于跨内容的传递,比如你说的100g的文档,我理解的是,让这个100g移动的命令是在内存中的,但是命令只是要求其从a文档移动到b文档,不经过内存。。。同时,如果有那种要经过内存的数据,就可以直接引用其值######我说的副本,理解是,比如服务器上有个PHP文档,我在浏览器请求这个php,那么这个php就把其代码复制张贴到内存中运行(所以这个副本跟前面的php就没有关系了),然后内存的代码运行得出一些数据。。######呵呵,不知道I/O是什么东西,都是自学的,这些没看到,读书的时候工科,所以c什么指针的不重要都在睡觉。######  所谓I/O就是输入输出。通俗说,就是硬盘的数据通道。你fopen一次,就占用一个通道(直到程序执行结束或fclose)。硬盘的I/O发展远没有容量发展的快。 所以硬盘容量可以十几个TB但是I/O还是差不多。  你说的副本这个原理,我也说不清楚,我也是自学的。 C语言也只是了解了一下而已。 不论PHP JS HTML都是载入内存来执行的。 但是会不会一个用户载入一个PHP我就不敢肯定了。 不过有一点可以肯定, 你在服务器修改程序,新的请求会得到新的程序执行的结果 。 而不需要重启PHP服务,这应该能证明你说的副本吧。 然后html不算编程语言,是标记语言,你不能说一个html文件是一个程序吧,程序的结果是可变的,纯html 是固定的。js不能操作文档不是因为它被载入内存。 PHP也被载入内存的,任何程序都要载入内存去执行。 关键在于js寄存的浏览器,没有给js操作权限。 js被包裹起来了。 只能通过浏览器去操作cookie之类的有严格限定的文件。 而php的解释器是拥有文件操作权限的。 当然只是有服务器的文件操作权限。 客户端的东西是不能操作的。 至少光凭它自己是不能的。 同样的,js也是不能操作服务器上的东西的。 就算是读取服务器的文件,也是要经过apache之类 的服务器软件来读取的。 js本身只是给服务器发个话。 服务器给不给返回,还是看服务器心情的。 很多东西个人理解会有偏差,我建议你有不理解的地方就查查文档。 比我这种业余的码农更权威。 ######还有就是不管i/O和内存,都是开始说的一个用户占用部分的东西,如果多个用户不是同时解析,那么,,就可以说成是fclose这个可以不写,当然写了最好######额,问下,你什么行业啊,以前学什么专业。。? 专业的书籍我看了一些,但是一两本书说的很少,同时国内的书确实不好,国外的书翻译的又老火。###### 我就是一个业余的爱好者而已。没学过什么专业,也不在什么行业。 纯兴趣。 当然以后就难说了。 老实说,我是最近一年才学的编程。 但是计算基础方面的东西积累了很多年,也有一定的了解了。 你叫我买书来看我真看不下去。 我的方法是,先看视频。 对一门语言有大概了解,然后把文档上的每一条都拿 来琢磨透,然后开发小项目。 当然我也没能吞下文档。 所以才成为业余的。 另外上面这个问题 如果多个用户不是同时请求或者用户很少,自然不需要fclose了。 不过也有可能程序结束没有关闭I/O连接导致进程关闭失败造成僵尸进程, 浪费了资源。也难说的。 ######呵呵,你让我想起了有,不要问我从哪里来,我不也不知道去哪里,我不属于任何地方,未来一切皆有可能的某部电影~~~~###### @kog-7 这是褒奖吗。。。。 ######回复 @Infinity : 改xml的php,写在上面,感觉用了很多重复的话######回复 @業餘碼農 : 那好多人都去提鞋了~我只是好奇好奇,你要是提鞋的,我就是给别人檫菊花的~!~######。。。。要是有个人对自己的身份工作支支吾吾遮遮掩掩,要么他是个特工黑客要么他就是个提鞋的。你觉得我像不像特工呢?######回复 @業餘碼農 : 呵呵,搞那么多标签干嘛嘛,你就是你,我只想了解你是干嘛的。######回复 @kog-7 : 。。。。。。。。。。。。农二代工一代码后代。######就是这个改xml,感觉写多了<?php header("Content-type: text/html; charset=utf-8"); print '<style> body{ background:rgba(223,238,231,0.9); } .error{color:rgb(182,69,69);font-size:60%;} .iput { border:1px solid black;      height:10%; background:rgb(223,238,231); font-family:"Microsoft YaHei",微软雅黑,helvetica; } #word0u { margin-left:2%; float:left; margin-top:5%; font-family:"Microsoft YaHei",微软雅黑,helvetica; } #input0u { list-style-type:none; float:left; margin-top:5%; } </style>'; print "<script> function closef() {window.parent.document.getElementById('screen').style.display='none';} </script>"; print '<body><button  style="cursor:pointer;border:1px;right:0px;top:0px;font-family:arial;font-weight:bolder;position:absolute" onclick="closef()">X</button>  '; $pro=true; if($_SERVER['REQUEST_METHOD']=="POST") { $pro=false;    if(empty($_POST['user'])||empty($_POST['pw'])||empty($_POST['pw2']))    {$pro=true;    print '<span class="error">'.iconv('gb2312','utf-8','请输入用户名和密码').' </span>';}    if(strlen($_POST['user'])>15)    {$pro=true;    print '<span class="error">'.iconv('gb2312','utf-8','用户名要小于5位数').' </span>';}    if(strlen($_POST['pw'])<5)    {$pro=true;    print '<span class="error">'.iconv('gb2312','utf-8','密码要大于5位数').' </span>';}    if(empty($_POST['pw'])!=empty($_POST['pw2']))    {$pro=true;    print '<span class="error">'.iconv('gb2312','utf-8','两次密码输入不一样').' </span>';}  $xmluser=new DOMDocument;  $xmluser->load('euser.xml');  $users=$xmluser->getElementsByTagName('user'); for($i=0;$i<$users->length;$i++) { if($users->item($i)->childNodes->item(0)->nodeValue==$_POST['user']) { $pro=true; print '<p class="error">'.iconv('gb2312','utf-8','有人用了这个用户名').'</p>';; break; } } } if(!$pro) { date_default_timezone_set('Asia/Shanghai');  $log= $xmluser->createElement('log');  $user= $xmluser->createElement('user');  $pw= $xmluser->createElement('pw');  $time=$xmluser->createElement('time'); $usert=$xmluser->createTextNode($_POST['user']); $pwt=$xmluser->createTextNode($_POST['pw']); $da=date("Y-m-d"); $timet=$xmluser->createTextNode($da); $user->appendChild($usert); $pw->appendChild($pwt); $time->appendChild($timet); $log->appendChild($user); $log->appendChild($pw); $log->appendChild($time); $xmluser->documentElement->appendChild($log); $xmluser->save('euser.xml'); print "<h2 style='font-family:微软雅黑,helvetica'>".iconv('gb2312','utf-8','欢迎').$_POST['user']." ".$da." ".iconv('gb2312','utf-8','您已注册')."</h2>"; $uu=$_POST['user']; $pp=$_POST['pw']; print "<script> window.parent.document.getElementById('user').innerHTML='hello<br>$uu'; window.parent.document.getElementById('login').style.display='none'; window.parent.document.getElementById('logon').style.display='none'; window.parent.document.getElementById('cookss').style.display='none'; window.parent.document.getElementById('clears').style.display='inherit'; window.parent.document.getElementById('chat').src='example1.html'; document.cookie='koguser=$uu'; </script></body>"; } else { print "<p style='font-family:arial;font-weight:bold;font-size:150%;letter-spacing:5px;margin-left:auto;margin-right:auto;width:70%;height:10%;text-align:center;margin-top:2%'>welcome</p>"; $_POST=array(); print  "<form action='elog.php' method='post'><ul id='word0u'><li>".iconv('gb2312','utf-8','用户名')."</li><br><li>" .iconv('gb2312','utf-8','密码')."</li><br><li>" .iconv('gb2312','utf-8','再次确认密码')."</li></ul> <ul id='input0u'><li><input class='iput' type='text' name='user' size='20'/></li><br> <li><input class='iput' type='password' name='pw' size='20'/></li><br> <li><input class='iput' type='password' name='pw2' size='20'/></li></ul><div><input style='border:2px solid black;clear:left;font-family:helvetica;background:rgb(223,238,231);margin-left:42%;margin-top:3%;font-size:18px;width:100px;text-align:center' type='submit' value=".iconv('gb2312','utf-8','注册')."></div></form></body>"; } ?> ###### 引用来自“Infinity”的评论首先,不论是PHP还是JS都不能修改客户端的文件。 你可以在客户端用JS修改XML数据,注意是数据,再传到服务器端用PHP保存成文档。 谢谢~

kun坤 2020-06-05 14:27:36 0 浏览量 回答数 0

问题

Java技术1000问(3)【精品问答】

问问小秘 2020-06-02 14:27:10 42 浏览量 回答数 1

回答

"首先,不论是PHP还是JS都不能修改客户端的文件。 你可以在客户端用JS修改XML数据,注意是数据,再传到服务器端用PHP保存成文档。######+1,网页不能允许你修改客户本地内容,得到数据然后后台根据这些数据再去读写服务器上的内容######我可以用js操作vba修改我本地的office文档,这是怎么回事######意识是不管xml放在服务器里面还是我本地的e盘里都不能修改吧?######回复 <a href=""http://my.oschina.net/u/1029302"" class=""referer"" target=""_blank"">@業餘碼農 : 映射可能不准确,应该是理解成副本要好点。######回复 <a href=""http://my.oschina.net/u/1029302"" class=""referer"" target=""_blank"">@業餘碼農 : 这两天脑壳想了很多。个人理解成,每个用户在处理php等的时候是获取其文档里面的一个映射,然后再处理。你说的fclose,我理解成很多用户在一个服务器里面映射了很多php文档,如果不关闭,每个映射在处理过程中都占用一定内存,但是~!~,如果没个用户使用映射的时间不一样,那么对于fclose就可有可无,因为反正用户使用映射完了传送数据给用户了,打开的文档就自动关闭,是把?######回复 <a href=""http://my.oschina.net/kog7"" class=""referer"" target=""_blank"">@kog-7 : 而unset,不一定是用来销毁数组的。 也可以用来销毁数组元素的。比如unset( $arr['a'] ); 这样就是纯粹的数组函数了。 关于PHP事件,不知道可不可以这样称呼, PHP只有一种事件,就是请求事件,就是说只有客户端请求它才会响应并执行。 当然如果你在服务器设置了计划任务那就另当别论了。 以上都是我的个人观点。经验之谈。 不一定正确。######回复 <a href=""http://my.oschina.net/kog7"" class=""referer"" target=""_blank"">@kog-7 : fclose你可能现在看不出作用。 但是大项目的时候,资源优化要做的很全面的。 一个用户读一个文件是1M,1000个用户同时读就是1G,并且占用1000个I/O资源,用完就手动fclose,而不是等到程序结束,这样就能在同一时刻减少I/O占用率( 有时你看到fclose靠近文件末尾,但那里有时并不代表程序结束。特别是面向对象程序设计 )。######回复 <a href=""http://my.oschina.net/u/1029302"" class=""referer"" target=""_blank"">@業餘碼農 : 就是点击,或者某个状态生成了激活某处功能。######<div class=""ref""> 引用来自“kog-7”的答案 我可以用js操作vba修改我本地的office文档,这是怎么回事 百度了一下 : Visual Basic for Applications(VBA)是Visual Basic的一种宏语言,主要能用来扩展Windows的应用程式功能,特别是Microsoft Office软件。也可说是一种应用程式视觉化的Basic Script。 关键是你能修改别的文档吗? ###### 引用来自“kog-7”的答案 意识是不管xml放在服务器里面还是我本地的e盘里都不能修改吧?  。。呃,关键不在于内存的占用。 而在于I/O的占用。 内存很便宜,但是I/O资源有限,你要知道像百度谷歌这样的大网站,每秒钟都会有几千上万的用户在同时操作。而且一个请求不是一秒就可以完成的。 虽说现在有什么负载均衡的技术,不过算下来,每时段的用户请求也不是小数目 。fclose要养成习惯。数据库也是一样。 遇到大项目就不易出问题。 你说的映射,或者副本,应该可以理解成C语言里的指针。 你可以想象一下,如果某个用户上传了一个100G的文件,如果要删除这个文件,是不是要把它载入内存? 我想不可能吧。  读取也是一样, 通过指针去读取数据流而已。 而不用把整个文件放入内存。 并且单个用户的内存占用是有限制的。所以fclose是省I/O。 ######如果没经过内存的,再要引用他,就要指定相关已被传输的文档,然后找起!!!是不? (限制字数,我分开回答)######同时我理解的js和html也如此,也是向文档请求,然后文档把其代码复制张贴到内存。。。这样子我觉得要容易理解一些,也很容易解释为什么你操作的js是不会反应到本来的js文档中的。。。。同时对于跨内容的传递,比如你说的100g的文档,我理解的是,让这个100g移动的命令是在内存中的,但是命令只是要求其从a文档移动到b文档,不经过内存。。。同时,如果有那种要经过内存的数据,就可以直接引用其值######我说的副本,理解是,比如服务器上有个PHP文档,我在浏览器请求这个php,那么这个php就把其代码复制张贴到内存中运行(所以这个副本跟前面的php就没有关系了),然后内存的代码运行得出一些数据。。######呵呵,不知道I/O是什么东西,都是自学的,这些没看到,读书的时候工科,所以c什么指针的不重要都在睡觉。######  所谓I/O就是输入输出。通俗说,就是硬盘的数据通道。你fopen一次,就占用一个通道(直到程序执行结束或fclose)。硬盘的I/O发展远没有容量发展的快。 所以硬盘容量可以十几个TB但是I/O还是差不多。  你说的副本这个原理,我也说不清楚,我也是自学的。 C语言也只是了解了一下而已。 不论PHP JS HTML都是载入内存来执行的。 但是会不会一个用户载入一个PHP我就不敢肯定了。 不过有一点可以肯定, 你在服务器修改程序,新的请求会得到新的程序执行的结果 。 而不需要重启PHP服务,这应该能证明你说的副本吧。 然后html不算编程语言,是标记语言,你不能说一个html文件是一个程序吧,程序的结果是可变的,纯html 是固定的。js不能操作文档不是因为它被载入内存。 PHP也被载入内存的,任何程序都要载入内存去执行。 关键在于js寄存的浏览器,没有给js操作权限。 js被包裹起来了。 只能通过浏览器去操作cookie之类的有严格限定的文件。 而php的解释器是拥有文件操作权限的。 当然只是有服务器的文件操作权限。 客户端的东西是不能操作的。 至少光凭它自己是不能的。 同样的,js也是不能操作服务器上的东西的。 就算是读取服务器的文件,也是要经过apache之类 的服务器软件来读取的。 js本身只是给服务器发个话。 服务器给不给返回,还是看服务器心情的。 很多东西个人理解会有偏差,我建议你有不理解的地方就查查文档。 比我这种业余的码农更权威。 ######还有就是不管i/O和内存,都是开始说的一个用户占用部分的东西,如果多个用户不是同时解析,那么,,就可以说成是fclose这个可以不写,当然写了最好######额,问下,你什么行业啊,以前学什么专业。。? 专业的书籍我看了一些,但是一两本书说的很少,同时国内的书确实不好,国外的书翻译的又老火。###### 我就是一个业余的爱好者而已。没学过什么专业,也不在什么行业。 纯兴趣。 当然以后就难说了。 老实说,我是最近一年才学的编程。 但是计算基础方面的东西积累了很多年,也有一定的了解了。 你叫我买书来看我真看不下去。 我的方法是,先看视频。 对一门语言有大概了解,然后把文档上的每一条都拿 来琢磨透,然后开发小项目。 当然我也没能吞下文档。 所以才成为业余的。 另外上面这个问题 如果多个用户不是同时请求或者用户很少,自然不需要fclose了。 不过也有可能程序结束没有关闭I/O连接导致进程关闭失败造成僵尸进程, 浪费了资源。也难说的。 ######呵呵,你让我想起了有,不要问我从哪里来,我不也不知道去哪里,我不属于任何地方,未来一切皆有可能的某部电影~~~~###### @kog-7 这是褒奖吗。。。。 ######回复 @Infinity : 改xml的php,写在上面,感觉用了很多重复的话######回复 @業餘碼農 : 那好多人都去提鞋了~我只是好奇好奇,你要是提鞋的,我就是给别人檫菊花的~!~######。。。。要是有个人对自己的身份工作支支吾吾遮遮掩掩,要么他是个特工黑客要么他就是个提鞋的。你觉得我像不像特工呢?######回复 @業餘碼農 : 呵呵,搞那么多标签干嘛嘛,你就是你,我只想了解你是干嘛的。######回复 @kog-7 : 。。。。。。。。。。。。农二代工一代码后代。######就是这个改xml,感觉写多了<?php header("Content-type: text/html; charset=utf-8"); print '<style> body{ background:rgba(223,238,231,0.9); } .error{color:rgb(182,69,69);font-size:60%;} .iput { border:1px solid black;      height:10%; background:rgb(223,238,231); font-family:"Microsoft YaHei",微软雅黑,helvetica; } #word0u { margin-left:2%; float:left; margin-top:5%; font-family:"Microsoft YaHei",微软雅黑,helvetica; } #input0u { list-style-type:none; float:left; margin-top:5%; } </style>'; print "<script> function closef() {window.parent.document.getElementById('screen').style.display='none';} </script>"; print '<body><button  style="cursor:pointer;border:1px;right:0px;top:0px;font-family:arial;font-weight:bolder;position:absolute" onclick="closef()">X</button>  '; $pro=true; if($_SERVER['REQUEST_METHOD']=="POST") { $pro=false;    if(empty($_POST['user'])||empty($_POST['pw'])||empty($_POST['pw2']))    {$pro=true;    print '<span class="error">'.iconv('gb2312','utf-8','请输入用户名和密码').' </span>';}    if(strlen($_POST['user'])>15)    {$pro=true;    print '<span class="error">'.iconv('gb2312','utf-8','用户名要小于5位数').' </span>';}    if(strlen($_POST['pw'])<5)    {$pro=true;    print '<span class="error">'.iconv('gb2312','utf-8','密码要大于5位数').' </span>';}    if(empty($_POST['pw'])!=empty($_POST['pw2']))    {$pro=true;    print '<span class="error">'.iconv('gb2312','utf-8','两次密码输入不一样').' </span>';}  $xmluser=new DOMDocument;  $xmluser->load('euser.xml');  $users=$xmluser->getElementsByTagName('user'); for($i=0;$i<$users->length;$i++) { if($users->item($i)->childNodes->item(0)->nodeValue==$_POST['user']) { $pro=true; print '<p class="error">'.iconv('gb2312','utf-8','有人用了这个用户名').'</p>';; break; } } } if(!$pro) { date_default_timezone_set('Asia/Shanghai');  $log= $xmluser->createElement('log');  $user= $xmluser->createElement('user');  $pw= $xmluser->createElement('pw');  $time=$xmluser->createElement('time'); $usert=$xmluser->createTextNode($_POST['user']); $pwt=$xmluser->createTextNode($_POST['pw']); $da=date("Y-m-d"); $timet=$xmluser->createTextNode($da); $user->appendChild($usert); $pw->appendChild($pwt); $time->appendChild($timet); $log->appendChild($user); $log->appendChild($pw); $log->appendChild($time); $xmluser->documentElement->appendChild($log); $xmluser->save('euser.xml'); print "<h2 style='font-family:微软雅黑,helvetica'>".iconv('gb2312','utf-8','欢迎').$_POST['user']." ".$da." ".iconv('gb2312','utf-8','您已注册')."</h2>"; $uu=$_POST['user']; $pp=$_POST['pw']; print "<script> window.parent.document.getElementById('user').innerHTML='hello<br>$uu'; window.parent.document.getElementById('login').style.display='none'; window.parent.document.getElementById('logon').style.display='none'; window.parent.document.getElementById('cookss').style.display='none'; window.parent.document.getElementById('clears').style.display='inherit'; window.parent.document.getElementById('chat').src='example1.html'; document.cookie='koguser=$uu'; </script></body>"; } else { print "<p style='font-family:arial;font-weight:bold;font-size:150%;letter-spacing:5px;margin-left:auto;margin-right:auto;width:70%;height:10%;text-align:center;margin-top:2%'>welcome</p>"; $_POST=array(); print  "<form action='elog.php' method='post'><ul id='word0u'><li>".iconv('gb2312','utf-8','用户名')."</li><br><li>" .iconv('gb2312','utf-8','密码')."</li><br><li>" .iconv('gb2312','utf-8','再次确认密码')."</li></ul> <ul id='input0u'><li><input class='iput' type='text' name='user' size='20'/></li><br> <li><input class='iput' type='password' name='pw' size='20'/></li><br> <li><input class='iput' type='password' name='pw2' size='20'/></li></ul><div><input style='border:2px solid black;clear:left;font-family:helvetica;background:rgb(223,238,231);margin-left:42%;margin-top:3%;font-size:18px;width:100px;text-align:center' type='submit' value=".iconv('gb2312','utf-8','注册')."></div></form></body>"; } ?> ###### 引用来自“Infinity”的评论首先,不论是PHP还是JS都不能修改客户端的文件。 你可以在客户端用JS修改XML数据,注意是数据,再传到服务器端用PHP保存成文档。 谢谢~"

montos 2020-06-04 13:24:13 0 浏览量 回答数 0

问题

SSH面试题

琴瑟 2019-12-01 21:46:22 3489 浏览量 回答数 0

回答

首先“缓存”Cache这个东西是干什么的,我们应该先有些基本的了解。要是不太明白的可以看看网上的解释:http://baike.baidu.com/view/907.htm 简单讲,阿里云OCS提供的功能就是提供对热点数据的高速访问。在使用OCS之前(或者在使用任何一种缓存服务之前),我们都应该明白关于缓存的这么几点: 缓存里的数据不是持久化保存的,也就是说它像是电脑里的内存,而不像硬盘;我们不能指望OCS里的数据一直保存不丢失。如果你真的需要存储持久化的数据,也许你应该出门左转找阿里云OSS(开发存储服务); 缓存里存的应该是“热点”数据。遵循常常出现的“20-80法则”,通常程序应用中都有一定比例的数据常常被请求访问,这就是所谓的热点数据,OCS正是为这种数据设计存在的。假定我们的程序中有100个数据,每次访问这些数据的概率完全是均匀分布的1/100,那么使用缓存的效果就不会太好,因为这其中不存在热点数据。 数据逐出。我们可以决定哪些数据是热点数据被放到缓存当中,但是如果我们的缓存容量不够大,这些热点数据中某些最近较少被用到的数据还是会被“挤出去”,这种行为叫做数据逐出。如果想减少出现这种情况,我们可以购买更高容量的OCS。 -------------------------         在开始使用之前,关于阿里云OCS,我们还需要知道以下这些事: 阿里云OCS仅支持阿里云内网访问,不支持公网访问。也就是说,我们用办公室或者家里的电脑(都属于公网)是无法连上阿里云OCS的。为什么会这样呢?因为缓存服务的根本目标是要提供低延迟的高速访问,而从公网电脑来连接OCS服务器的场景下,公网的网络环境是不可控的,可能出现延迟很高甚至断连接的情况,这使得缓存服务无法保证“高速、低延迟”的基本特性,所以阿里云OCS是不支持公网直接访问的。如果觉得高延迟的情况对于我们的应用也能接受,那么我们应该去选择阿里云其他的产品(比如OSS开放存储服务),而不应该选择OCS缓存服务。 阿里云OCS需要与ECS(阿里云服务器)配合使用,而且只能与本地区节点的ECS连通。这一点与上一条相关。OCS只能从阿里云内网访问,也就是说我们只能从阿里云ECS上才能访问并使用OCS服务。所以我们在官网购买OCS的时候,会看到提示信息说需要至少有一台ECS才能买OCS。另外,阿里云ECS是分地区节点的,比如北京、杭州、青岛等,我们在购买OCS缓存的时候也要选相应的地区节点。北京的ECS只能访问北京的OCS,而不能访问杭州或青岛的OCS。 阿里云OCS是按购买量收费的,而不是按使用量收费。这点需要提醒新同学们注意,在我们购买了OCS缓存之后,计费就已经开始了,即使我们还没有真正使用缓存。也就是说,我们买了1G的OCS缓存后,即使目前使用量为0,系统也会按照1G的标准来计费。所以我们在购买OCS的时候,要选取适合我们业务数据需要的缓存档位。当然了,阿里云OCS也提供在线升降缓存容量的功能。也就是说,如果我们在使用了一段时间之后,发现购买的OCS缓存不够用了(或者缓存使用量太低),我们可以在线的对已有的OCS实例进行升档(或者降档),而OCS缓存服务不会被中断。 阿里云OCS对于存贮的对象大小是有限制的。缓存通常对其内部存储的数据尺寸是有限制的,阿里云OCS也一样。目前OCS支持存储的数据对象的上限是1,000,000Byte。如果要存的值超过这个限制,我们应该考虑把数据压缩,或从逻辑上分成不同键存储的几个值。 ------------------------- 现在我们开始在阿里云官网上购买OCS实例  http://buy.aliyun.com/ocs  首先我们需要已经有了一台阿里云ECS,否则我们无法在这个页面成功购买OCS。购买的第一步,我们先要确定选择买哪个地区的OCS;这个很重要,如上面所说,如果我们的ECS是属于北京,而我们在这里购买了杭州的OCS,那么这两者是无法配合协同工作的。所以,在购买OCS的时候一定要选择应用服务器ECS所在地区的OCS。下一步是要选择OCS缓存容量。我们要购买多大的缓存,这个取决于我们对自身业务应用中热点数据总量大小的判断。如果一时难以准确判断数据量,也不用担心:我们可以先买一个大致容量的OCS(比如1GB),随后在使用过程中,通过OCS控制台提供的监控功能,我们可以了解到目前OCS缓存的使用量等数据,然后可以自主的调整所需的缓存量,购买更大的缓存(比如升到5GB)或者减少已购的缓存量(比如降到512MB),阿里云会根据我们选择的新配置来调整对应的收费。此外在选择缓存容量的时候,要知道不同容量的缓存档位对应着不同的性能配额,具体来说包括两个指标:吞吐量带宽与每秒请求处理数(QPS)。比如以现在的配额标准,1GB的OCS缓存对应5MB/sec的吞吐量带宽和3000次/sec的请求处理峰值。当我们使用OCS的时候,如果数据量传输的带宽超过了5MB/s, 或者每秒的请求数超过了3000次,都会触发性能配额控制机制,导致某些请求无法返回正常结果。在确定了地区和缓存容量之后,我们就可以直接下单购买OCS了。 ------------------------- 在成功购买OCS之后,我们的联系邮箱和手机都会收到OCS创建成功的通知,里面会包括OCS的实例ID和初始密码(关于密码的用处后面会讲到)。我们现在登录OCS控制台, http://ocs.console.aliyun.com/ 就可以看到已经购买到的OCS实例列表。在列表页面上对应OCS实例的后面点击“管理”,就可以进入该OCS实例的详情页,看到更多的详细信息。 ------------------------- 我们现在已经有了一个OCS缓存实例,现在是时候试玩OCS了。要使用OCS就要写一点程序代码,不过不用担心,我们在这里采用“Happy-Path”的方法,从最简单的操作开始,让新上手的菜鸟们能马上就有一个能调用OCS缓存服务的程序。OCS提供缓存服务,它并不要求我们的程序是哪种语言来写的。我们这里先以Java程序为例,写一个最简单的“Hello World”。(其他编程语言的例子,我们随后附上。)第一步,登录你的阿里云ECS服务器,在上面安装Java JDK和你常用的IDE(比如Eclipse)。一定要记得我们之前说过的,只有在阿里云内网的ECS服务器上,才能访问我们的OCS实例。所以,用家里或是公司的电脑执行下面的代码示例是看不到结果的。 Java JDK和Eclipse都很容易从网上找到下载,比如 http://download.eclipse.org/ 或者 http://www.onlinedown.net/soft/32289.htm 第二步,在把Java开发环境准备好了之后,下载第一个代码示例(Sample-Code-1第三步,在Eclipse里面打开刚下载的OcsSample1.java,我们要根据自己的OCS实例信息修改几个地方。        我们每个人买到的OCS实例的ID都是不重复的,其对应的阿里云内网地址也是独一无二的,这些信息都在OCS控制台上显示出来。我们在同自己的OCS实例建立连接的时候,需要根据这些信息修改OcsSample1.java中的对应地方。         public static void main(String[] args) {                                        final String host = "b2fd2f89f49f11e3.m.cnqdalicm9pub001.ocs.aliyuncs.com"; //控制台上的“内网地址”                   final String port ="11211";       //默认端口 11211,不用改                   final String username = "b2fd2f89f49f11e3"; //控制台上的“访问账号”                   final String password = "my_password"; //邮件或短信中提供的“密码”                   …… …… ……       信息修改完毕,我们可以运行自己的程序了。运行main函数,我们会在Eclipse下面的console窗口看到下面这样的结果(请忽略可能出现的红色INFO调试信息): OCS Sample CodeSet操作完成!Get操作: Open Cache Service,  from www.Aliyun.com     OK,搞定!我们已经成功的连接上了阿里云的OCS并且调用缓存服务成功,就这么简单。-------------------------我们已经成功运行了第一个调用阿里云OCS缓存服务的Sample程序OcsSample1.java,现在我们看看这个程序里都做了什么。                                  …… …… ……                            System.out.println("OCS Sample Code");                                                        //向OCS中存一个key为"ocs"的数据,便于后面验证读取数据,                             //这个数据对应的value是字符串 Open Cache Service,  from www.Aliyun.com                            OperationFuture future = cache.set("ocs", 1000," Open Cache Service,  from www.Aliyun.com");                            //向OCS中存若干个数据,随后可以在OCS控制台监控上看到统计信息                            for(int i=0;i<100;i++){                                String key="key-"+i;                                String value="value-"+i;                                 //执行set操作,向缓存中存数据                                cache.set(key, 1000, value);                            }                             System.out.println("Set操作完成!");                             future.get();  //  确保之前(cache.set())操作已经结束                         //执行get操作,从缓存中读数据,读取key为"ocs"的数据                            System.out.println("Get操作:"+cache.get("ocs"));                            …… …… …… 从这些代码中可以看出: 1. 我们在建立与OCS缓存服务器的连接后,先是向缓存中存(set)了一个“key-value”(键值对)形式的数据,这个数据的key是字符串“ocs”,其对应的value也是字符串;2. 接着我们继续向缓存中存(set)了100个其他简单的“key-value”数据。3. 最后我们进行功能验证。根据之前给定的key,从缓存中获取(get)其对应的value:也就是输入字符串“ocs”,缓存给我们返回value对应的字符串。 以上的步骤中,1与3是相对应的,我们只有先向缓存中set了某个数据,后面才能从缓存中get到这个数据。步骤2中程序向缓存set了100个数据,是为了从另一个方面进行验证。我们回到阿里云OCS控制台,打开“实例详情”页,在“实例监控”的部分点击刷新,会看到其中一些监控项的值已经发生了变化(注:监控信息的刷新可能存在数秒的延迟), 其中的“Key的个数”已经变成了101,也就是说我们程序已经成功地向OCS缓存中存放了101个数据。

唐翰 2019-12-01 23:27:50 0 浏览量 回答数 0

回答

首先“缓存”Cache这个东西是干什么的,我们应该先有些基本的了解。要是不太明白的可以看看网上的解释:http://baike.baidu.com/view/907.htm 简单讲,阿里云OCS提供的功能就是提供对热点数据的高速访问。在使用OCS之前(或者在使用任何一种缓存服务之前),我们都应该明白关于缓存的这么几点: 缓存里的数据不是持久化保存的,也就是说它像是电脑里的内存,而不像硬盘;我们不能指望OCS里的数据一直保存不丢失。如果你真的需要存储持久化的数据,也许你应该出门左转找阿里云OSS(开发存储服务); 缓存里存的应该是“热点”数据。遵循常常出现的“20-80法则”,通常程序应用中都有一定比例的数据常常被请求访问,这就是所谓的热点数据,OCS正是为这种数据设计存在的。假定我们的程序中有100个数据,每次访问这些数据的概率完全是均匀分布的1/100,那么使用缓存的效果就不会太好,因为这其中不存在热点数据。 数据逐出。我们可以决定哪些数据是热点数据被放到缓存当中,但是如果我们的缓存容量不够大,这些热点数据中某些最近较少被用到的数据还是会被“挤出去”,这种行为叫做数据逐出。如果想减少出现这种情况,我们可以购买更高容量的OCS。 -------------------------         在开始使用之前,关于阿里云OCS,我们还需要知道以下这些事: 阿里云OCS仅支持阿里云内网访问,不支持公网访问。也就是说,我们用办公室或者家里的电脑(都属于公网)是无法连上阿里云OCS的。为什么会这样呢?因为缓存服务的根本目标是要提供低延迟的高速访问,而从公网电脑来连接OCS服务器的场景下,公网的网络环境是不可控的,可能出现延迟很高甚至断连接的情况,这使得缓存服务无法保证“高速、低延迟”的基本特性,所以阿里云OCS是不支持公网直接访问的。如果觉得高延迟的情况对于我们的应用也能接受,那么我们应该去选择阿里云其他的产品(比如OSS开放存储服务),而不应该选择OCS缓存服务。 阿里云OCS需要与ECS(阿里云服务器)配合使用,而且只能与本地区节点的ECS连通。这一点与上一条相关。OCS只能从阿里云内网访问,也就是说我们只能从阿里云ECS上才能访问并使用OCS服务。所以我们在官网购买OCS的时候,会看到提示信息说需要至少有一台ECS才能买OCS。另外,阿里云ECS是分地区节点的,比如北京、杭州、青岛等,我们在购买OCS缓存的时候也要选相应的地区节点。北京的ECS只能访问北京的OCS,而不能访问杭州或青岛的OCS。 阿里云OCS是按购买量收费的,而不是按使用量收费。这点需要提醒新同学们注意,在我们购买了OCS缓存之后,计费就已经开始了,即使我们还没有真正使用缓存。也就是说,我们买了1G的OCS缓存后,即使目前使用量为0,系统也会按照1G的标准来计费。所以我们在购买OCS的时候,要选取适合我们业务数据需要的缓存档位。当然了,阿里云OCS也提供在线升降缓存容量的功能。也就是说,如果我们在使用了一段时间之后,发现购买的OCS缓存不够用了(或者缓存使用量太低),我们可以在线的对已有的OCS实例进行升档(或者降档),而OCS缓存服务不会被中断。 阿里云OCS对于存贮的对象大小是有限制的。缓存通常对其内部存储的数据尺寸是有限制的,阿里云OCS也一样。目前OCS支持存储的数据对象的上限是1,000,000Byte。如果要存的值超过这个限制,我们应该考虑把数据压缩,或从逻辑上分成不同键存储的几个值。 ------------------------- 现在我们开始在阿里云官网上购买OCS实例  http://buy.aliyun.com/ocs  首先我们需要已经有了一台阿里云ECS,否则我们无法在这个页面成功购买OCS。购买的第一步,我们先要确定选择买哪个地区的OCS;这个很重要,如上面所说,如果我们的ECS是属于北京,而我们在这里购买了杭州的OCS,那么这两者是无法配合协同工作的。所以,在购买OCS的时候一定要选择应用服务器ECS所在地区的OCS。下一步是要选择OCS缓存容量。我们要购买多大的缓存,这个取决于我们对自身业务应用中热点数据总量大小的判断。如果一时难以准确判断数据量,也不用担心:我们可以先买一个大致容量的OCS(比如1GB),随后在使用过程中,通过OCS控制台提供的监控功能,我们可以了解到目前OCS缓存的使用量等数据,然后可以自主的调整所需的缓存量,购买更大的缓存(比如升到5GB)或者减少已购的缓存量(比如降到512MB),阿里云会根据我们选择的新配置来调整对应的收费。此外在选择缓存容量的时候,要知道不同容量的缓存档位对应着不同的性能配额,具体来说包括两个指标:吞吐量带宽与每秒请求处理数(QPS)。比如以现在的配额标准,1GB的OCS缓存对应5MB/sec的吞吐量带宽和3000次/sec的请求处理峰值。当我们使用OCS的时候,如果数据量传输的带宽超过了5MB/s, 或者每秒的请求数超过了3000次,都会触发性能配额控制机制,导致某些请求无法返回正常结果。在确定了地区和缓存容量之后,我们就可以直接下单购买OCS了。 ------------------------- 在成功购买OCS之后,我们的联系邮箱和手机都会收到OCS创建成功的通知,里面会包括OCS的实例ID和初始密码(关于密码的用处后面会讲到)。我们现在登录OCS控制台, http://ocs.console.aliyun.com/ 就可以看到已经购买到的OCS实例列表。在列表页面上对应OCS实例的后面点击“管理”,就可以进入该OCS实例的详情页,看到更多的详细信息。 ------------------------- 我们现在已经有了一个OCS缓存实例,现在是时候试玩OCS了。要使用OCS就要写一点程序代码,不过不用担心,我们在这里采用“Happy-Path”的方法,从最简单的操作开始,让新上手的菜鸟们能马上就有一个能调用OCS缓存服务的程序。OCS提供缓存服务,它并不要求我们的程序是哪种语言来写的。我们这里先以Java程序为例,写一个最简单的“Hello World”。(其他编程语言的例子,我们随后附上。)第一步,登录你的阿里云ECS服务器,在上面安装Java JDK和你常用的IDE(比如Eclipse)。一定要记得我们之前说过的,只有在阿里云内网的ECS服务器上,才能访问我们的OCS实例。所以,用家里或是公司的电脑执行下面的代码示例是看不到结果的。 Java JDK和Eclipse都很容易从网上找到下载,比如 http://download.eclipse.org/ 或者 http://www.onlinedown.net/soft/32289.htm 第二步,在把Java开发环境准备好了之后,下载第一个代码示例(Sample-Code-1第三步,在Eclipse里面打开刚下载的OcsSample1.java,我们要根据自己的OCS实例信息修改几个地方。        我们每个人买到的OCS实例的ID都是不重复的,其对应的阿里云内网地址也是独一无二的,这些信息都在OCS控制台上显示出来。我们在同自己的OCS实例建立连接的时候,需要根据这些信息修改OcsSample1.java中的对应地方。         public static void main(String[] args) {                                        final String host = "b2fd2f89f49f11e3.m.cnqdalicm9pub001.ocs.aliyuncs.com"; //控制台上的“内网地址”                   final String port ="11211";       //默认端口 11211,不用改                   final String username = "b2fd2f89f49f11e3"; //控制台上的“访问账号”                   final String password = "my_password"; //邮件或短信中提供的“密码”                   …… …… ……       信息修改完毕,我们可以运行自己的程序了。运行main函数,我们会在Eclipse下面的console窗口看到下面这样的结果(请忽略可能出现的红色INFO调试信息): OCS Sample CodeSet操作完成!Get操作: Open Cache Service,  from www.Aliyun.com     OK,搞定!我们已经成功的连接上了阿里云的OCS并且调用缓存服务成功,就这么简单。-------------------------我们已经成功运行了第一个调用阿里云OCS缓存服务的Sample程序OcsSample1.java,现在我们看看这个程序里都做了什么。                                  …… …… ……                            System.out.println("OCS Sample Code");                                                        //向OCS中存一个key为"ocs"的数据,便于后面验证读取数据,                             //这个数据对应的value是字符串 Open Cache Service,  from www.Aliyun.com                            OperationFuture future = cache.set("ocs", 1000," Open Cache Service,  from www.Aliyun.com");                            //向OCS中存若干个数据,随后可以在OCS控制台监控上看到统计信息                            for(int i=0;i<100;i++){                                String key="key-"+i;                                String value="value-"+i;                                 //执行set操作,向缓存中存数据                                cache.set(key, 1000, value);                            }                             System.out.println("Set操作完成!");                             future.get();  //  确保之前(cache.set())操作已经结束                         //执行get操作,从缓存中读数据,读取key为"ocs"的数据                            System.out.println("Get操作:"+cache.get("ocs"));                            …… …… …… 从这些代码中可以看出: 1. 我们在建立与OCS缓存服务器的连接后,先是向缓存中存(set)了一个“key-value”(键值对)形式的数据,这个数据的key是字符串“ocs”,其对应的value也是字符串;2. 接着我们继续向缓存中存(set)了100个其他简单的“key-value”数据。3. 最后我们进行功能验证。根据之前给定的key,从缓存中获取(get)其对应的value:也就是输入字符串“ocs”,缓存给我们返回value对应的字符串。 以上的步骤中,1与3是相对应的,我们只有先向缓存中set了某个数据,后面才能从缓存中get到这个数据。步骤2中程序向缓存set了100个数据,是为了从另一个方面进行验证。我们回到阿里云OCS控制台,打开“实例详情”页,在“实例监控”的部分点击刷新,会看到其中一些监控项的值已经发生了变化(注:监控信息的刷新可能存在数秒的延迟), 其中的“Key的个数”已经变成了101,也就是说我们程序已经成功地向OCS缓存中存放了101个数据。-------------------------在写下一篇技术贴之前,列一些OCS用户在入门时问到的问题,方便其他刚认识OCS的同学:Question:买了1G的OCS,那就相当于这个1G是专门缓存用的,与ECS服务器的内存没关系是吧~Answer:是的,OCS的缓存容量与您ECS的内存容量是没关系的。Question:OCS 外网测试,怎么连接?有没有外网连接地址哦?Answer:OCS是不能从外网访问的。参照上面的文章。Question:我之前那个OCS可以正常使用,但现在换了一个OCS就不行了,怎么回事?Answer:经核实您的主机是属于杭州节点的,而现在这个OCS是青岛节点的,不同地域之间的产品内网不互通。Question:在设置一个value时,如果指定过期时间为0,会永久保留吗?Answer:指定过期时间为0,OCS就认为此数据不根据过期时间发生淘汰;但是,此数据仍有可能基于LRU被其他数据淘汰,或者由内存清理造成丢失 ,因此不能认为这个value会永久保留。 Question:对OCS的访问是否需要负载均衡? Answer:不需要。对访问请求的负载均衡都是在OCS服务器端来进行的,用户直接使用缓存服务即可,不用考虑负载均衡的事情。 Question:OCS是否会主动关闭闲置的连接? 如果会,请问连接闲置多久会被关闭?Answer:OCS不会主动关闭闲置的用户连接。但是用户的环境如果使用了SLB,则需要参考SLB连接关闭时间。Question:如何设置数据在OCS缓存中的过期时间 ?Answer:关于设置缓存数据的过期时间,可以参考Memcached官方说明: https://code.google.com/p/memcached/wiki/NewCommands An expiration time, in seconds. Can be up to 30 days. After 30 days, is treated as a unix timestamp of an exact date. 翻译过来就是:0~2592000表示从当前时刻算起的时间长度(以秒计算,最长2592000即30天);大于2592000表示UNIX时间戳。 此值设置为0表明此数据不会主动过期。------------------------- 回 12楼(村里一把手) 的帖子 谢谢,要让大家用得好才算数。 -------------------------缓存与数据库相结合使用,是常见的一种应用搭配场景。现在我们再看一个例子,是用OCS搭配MySQL数据库使用。Java示例代码在此(这个示例代码中,大部分与前几个例子类似。因为要与数据库结合,所以程序需要依赖一个JDBC的jar包才能运行。支持MySQL的JDBC jar包在此(在程序中添加MySQL数据库的连接信息:     …… …… ……            // JDBC driver name and database URL    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";    static final String DB_URL = "jdbc:mysql://xxxxxxx.mysql.rds.aliyuncs.com/testdb"; //MySQL数据库URL        //  Database用户名及密码    static final String DB_USER = "xxxxxx";    static final String DB_PASS = "xxxxxx";            我们设想这样一个场景:我们需要从数据库的tableone表中查找区域不属于北京的记录总数,用SQL表示就是:SELECT count(*)  FROM testdb.tableone where region != 'beijing'假定这个表中的数据如下,则这条SQL查询返回的结果就是7:如果这个查询被调用到的频率很高,多个用户反复不断的在数据库中查这个数据,我们就可以把这个查询结果放到OCS缓存中去。看下面的代码片段,我们用for循环模拟用户连续20次在数据库中查询上述SQL语句:              for (int i = 1; i <= 20; i++) {                String sql = "SELECT count(*)  FROM testdb.tableone where region != 'beijing'";                String key ="non-beijing"; //给SQL语句自定义一个key                //在OCS缓存里按key查找               String value =  (String) cache.get(key);                                if (value == null) {                    // 在OCS缓存里没有命中                    // step 1:从My SQL数据库中查询                    //Load MySQL Driver                      Class.forName(JDBC_DRIVER);                     con = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);                    ps = con.prepareStatement(sql);                    ResultSet result = ps.executeQuery(sql);                    result.next();                                        value=result.getString(1);                    System.out.println("从MySQL中查询数据.  Key= "+key+" Value="+value);                                       // step 2: 把数据库返回的数据作为value存放到OCS缓存中去                    cache.set(key, EXPIRE_TIME, value);                                    } else {                    // 在OCS缓存里命中                    System.out.println("从OCS中读取数据.     Key= "+key+" Value="+value);                }                            }// end of for在这段代码中我们可以看到,我们给这条SQL语句标记了一个key,当有用户要执行这条SQL的时候,我们首先按照key在OCS缓存中查找:如果没有对应的缓存数据,则连接MySQL数据库执行SQL查询,把结果返回给用户,并把这个查询结果存到OCS缓存中去;如果OCS中已经有了对应的缓存数据,则直接把缓存数据返回给用户。运行结果如下: 从MySQL中查询数据.  Key= non-beijing, Value=7从OCS中读取数据.     Key= non-beijing, Value=7从OCS中读取数据.     Key= non-beijing, Value=7从OCS中读取数据.     Key= non-beijing, Value=7…… …… 从结果可以看出,程序第1次是从MySQL数据库当中查询数据,后面的19次都是从OCS缓存中获取key对应的value直接返回。也就是说,OCS降低了程序去连接MySQL数据库执行SQL查询的次数,减轻了对数据库的负载压力。用户对热点数据访问的频率越高,OCS的这种优势就越明显。

唐翰 2019-12-01 23:41:23 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站