推荐一款网络海美迪机顶盒哪一款容易上手?送亲戚

我家刚办了移动机互联网电视,只配了一个机顶盒子,而我家有两个电视,一个老彩电,一个液晶,如果把亲戚_百度知道
我家刚办了移动机互联网电视,只配了一个机顶盒子,而我家有两个电视,一个老彩电,一个液晶,如果把亲戚
我家刚办了移动机互联网电视,只配了一个机顶盒子,而我家有两个电视,一个老彩电,一个液晶,如果把亲戚家闲置的移动魔百盒拿过来装上有用吗?如果买一个一样的机顶盒多少钱...
我家刚办了移动机互联网电视,只配了一个机顶盒子,而我家有两个电视,一个老彩电,一个液晶,如果把亲戚家闲置的移动魔百盒拿过来装上有用吗?如果买一个一样的机顶盒多少钱
答题抽奖
首次认真答题后
即可获得3次抽奖机会,100%中奖。
来自电脑网络类芝麻团
采纳数:8599
获赞数:12252
参与团队:
可以用,建议不要买副机,副机价格是便宜,但是没有网络机顶盒(例如天猫魔盒)好用
啥叫副机?
你不是要装两个机顶盒吗,如果是第一台就叫主机,如果再加一台就是副机
你不是要装两个机顶盒吗,如果是第一台就叫主机,如果再加一台就是副机
两个号码满98送宽带,先交480互联网电视费两年,套餐划算吗
天猫魔盒到哪买?多少钱好?
天猫上面可以买啊,也就199
副机为什么不好用呢?不好意思,我不懂的太多了
你不认为办理电视送的那个机顶盒功能太少了吗,还有搜的台也不多还有广告,天猫魔盒不一样,功能多搜的台也多还没有广告
因为还没装,还不知道,😝我上面说的套餐划算吗?
唏雯狮子座
唏雯狮子座
采纳数:474
获赞数:1068
擅长:暂未定制
有用的,100块左右
移动的说,再买一个两三百,还没来装不知道什么牌子
你要到市场去看一下,不要听他说,有可能他是想你买他家的产品
不用谢,希望能对你有帮助
坟地上唱忐忑
坟地上唱忐忑
采纳数:280
获赞数:826
擅长:暂未定制
为你推荐:
其他类似问题
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。还没有帐号? 赶紧
用户版块帖子
网络机顶盒哪个好用?买这四个品牌准没错!
UID:2930797
在线时间3小时
M币-592专家-6
&&发表于: 06-25
网络机顶盒哪个好用?买这四个品牌准没错!
网络机顶盒这个概念诞生的比较早,在影碟机那个时代就已经有了雏形,宽带网络不断提速,网络机顶盒的功能已从一个多频率的调谐器和解码器跃升为大量电影、多媒体事件、新闻等联机数据库的一个控制终端,当然网络机顶盒品牌也多样化,市面上著名品牌也不多,买这四个品牌网络机顶盒准没错。=740) window.open('http://5b.cdn.sohucs.com/images/a55f0efce94eeb825b9264ced12a14.jpeg');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="网络机顶盒哪个好用?买这四个品牌准没错!" alt="网络机顶盒哪个好用?买这四个品牌准没错!">一、 泰捷网络机顶盒=740) window.open('http://5b.cdn.sohucs.com/images/e845a48f23d4e98bc07b3.jpeg');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="网络机顶盒哪个好用?买这四个品牌准没错!" alt="网络机顶盒哪个好用?买这四个品牌准没错!">泰捷的影音技术与企业级解决方案应用于全球多家知名互联网公司,是唯一一家专注于电视盒子领域,并拥有相当强的研发技术实力的团队,也是国内为数不多软件与硬件全产业链的团队,拥有独创的6大核心技术,十三项品质体验最低标准,无广告、操作必须简单、品质过硬、系统持续半年以上流畅等等,获得了消费者的广泛认可,被亲切称为盒子中的苹果手机。泰捷机顶盒还是一款网红盒子,被诸多热门娱乐综艺推荐,种草!为了让人幸福,他们做到了极致,不断的给人惊喜、制造好彩头,举办万人祈福活动,通过技术去带给家人温度、连接家人。是当之无愧的“幸运盒子”,用来送家人、送朋友、送亲戚不错的选择。有很多网络机顶盒品牌往往不注重品牌经营,抱着捞一把就跑的想法,虚标配置,在盒子里面植入大量广告,给消费者用的闹心,败坏了整个网络机顶盒的市场氛围,所以买电视盒子一定要买大品牌。二、 天猫网络机顶盒=740) window.open('http://5b.cdn.sohucs.com/images/c9c070ff84e1b8e055.png');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="网络机顶盒哪个好用?买这四个品牌准没错!" alt="网络机顶盒哪个好用?买这四个品牌准没错!">阿里作为国内数一数二的互联网企业,天猫机顶盒作为阿里打通线下交流重要一环,在硬件和价格上面阿里都有无以伦比优势,特别是阿里云专门为电视机顶盒开发系统更是受到不少好评,当然相对来说阿里云系统也具有一定封闭性。三、 华为网络机顶盒=740) window.open('http://5b.cdn.sohucs.com/images/cc8bc865cfb.jpeg');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="网络机顶盒哪个好用?买这四个品牌准没错!" alt="网络机顶盒哪个好用?买这四个品牌准没错!">华为是国内少数几家有自主生产芯片能力的厂商,华为荣耀机顶盒作为国内唯一才有自产芯片的产品,实现了硬件层面上的专属定制,在解码和调谐有着无可比拟优势,当然国产芯片在兼容性上面也会存在一点小问题。四、 小米网络机顶盒=740) window.open('http://5b.cdn.sohucs.com/images/d40bbf2e.jpeg');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="网络机顶盒哪个好用?买这四个品牌准没错!" alt="网络机顶盒哪个好用?买这四个品牌准没错!">小米生产机顶盒的历史不比手机短,有相当丰富的技术积累,小米机顶盒也是所有厂家里面档次最多的,各种不同价位都有,当然一分钱一分货,选择低价小米盒子虽然体验不错,但是也会经常提醒内存不足。
UID:135975
在线时间4590小时
M币2989专家36
&发表于: 06-26
150块的T1默秒全
UID:2161443
在线时间14小时
M币652专家2
&发表于: 06-26
确定阿里云系统的破盒子默秒全?看来大家是都忘了删应用的事情了
UID:814681
在线时间1290小时
M币689专家1
&发表于: 06-26
坚决淘汰阿里云,我用的是斐讯盒子,很好。
UID:1566581
在线时间86小时
M币321专家1
&发表于: 06-30
斐讯盒子斐讯盒子斐讯盒子
UID:671363
在线时间899小时
M币677专家2
&发表于: 06-30
阿里云首先pass,垃圾山寨系统
UID:81584
在线时间4691小时
M币38995专家47
&发表于: 07-01
不能装应用就算了,它还强行删应用,谁去买。
访问内容超出本站范围,不能确定是否安全
温馨提示:欢迎交流讨论,请勿发布纯表情、纯引用等灌水帖子;以免被删除
您目前还是游客,请
&回复后跳转到最后一页
Code by , Time now is:08-16 07:33, Total 0.157440(s) query 11,
Gzip enabled&2018新手买盒子必看榜单:电视机顶盒十大品牌
稿源:用户投稿
面对市场琳琅满目的电视盒子,各种配置参数,不同的外观造型,肯定愁坏了不少选择困难症,那么市场上面哪些电视盒子最好呢?小编精选市面上最畅销十大品牌进行比较。一、 && 泰捷盒子泰捷是大家耳熟能详的电视盒子品牌,他们每一台电视盒子成品都是精品中的精品,对用料的选材都是欧美、日本进口,泰捷盒子专业度高,还有一个很重要的原因,他们是采用欧美的品质生产标准,这在电视盒子行业里是很少见的,每50个成品只有约30个达标,非常严格,更是采用业内独家环形扇翼散热通道,散热性能比前代产品提升80%,与一般盒子相比,使用寿命提升至少半年,如同盒子中苹果手机一样经久耐用。泰捷非常用心在经营品牌为了让人幸福,他们做到了极致,不断的给人惊喜、制造好彩头,曾推出一元养幸福,万人祈福等活动,被时尚圈媒体评为“幸运盒子”,是送家人、送朋友、送亲戚不错的选择。选购电视机顶盒不能盲目看配置,有些厂家混淆概念,配置虚标或者采用廉价材料,不要相信物美价廉,多看商品评价,总体来说选购公信度较高的大品牌一定没有错。二、泰捷webox mix泰捷webox mix可以说是电视盒子界一次伟大的创新,视频通话安防功能已经成为很多家庭的标配,泰捷webox mix巧妙的把电视盒子、智能音响、智能视频通话这三大功能集合于一身,有效减少客厅电子产品使用空间,让家中马上实现智能化。三、小米盒子小米盒子是小米生态链中重要一环,小米产品品质自然不用说重要的是非常便捷的解决方案,可以说米家系统算所有智能家居里面做的最好的,不过智能家居这个概念刚刚起步,稍有bug还是能够原谅的。四、华为荣耀盒子芯片一直是国内科技的短板,华为荣耀盒子是采用完全自主研发的芯片,这点够值得掏腰包,当然自产芯片在整体性能上还是弱于国际大牌芯片,但是一对一定制有着无可比拟的优势。五、迪优美特盒子迪优美特算比较老的国内硬件品牌,在ktv设备上面很多设备是采用迪优美特的产品,所以迪优美特的电视盒子便宜还可以扩展嗨歌功能,当然硬件厂商在系统上面一直不是很占优势。六、天猫盒子很多人了解的第一款电视盒子应该就是天猫盒子了,毕竟淘宝上面铺天盖地广告,搜索电视盒子的首页推荐,天猫盒子在硬件上的配置无可挑剔,阿里云在资源上面也有相当大的优点,当然阿里云平台不支持其他视频app。七、腾讯企鹅盒子腾讯视频是喜欢看美剧不会翻墙的小伙伴唯一选择,最近腾讯狂推最新版企鹅盒子,不过细心小伙伴会发现腾讯盒子和创维T1盒子配置一模一样,你们没猜对,创维就是腾讯盒子的代工厂。八、爱奇艺电视果价格不便宜,硬件配置远低于同价位的电视盒子,系统也做的一般,官方快2年没有更新,但是看到它的外观起,很多消费者已经不需要太多理由,毕竟有颜值还要什么理由呢。九、开博尔电视盒子爱奇艺电视果是偏科的,开博尔电视盒子更偏科,硕大体积,系统体验一般,昂贵的价格,当然开博尔是市面上唯一能够给你蓝光享受的电视盒子,画质致胜的小伙伴一点不能够错过。十、泰捷 WEBOX AIR(40)泰捷webox air(40)是市面上唯一一款真3G内存的电视盒子,泰捷加量不加价,WEBOX WE40采用非常精密的苹果工艺,这是泰捷做硬件这么多年来,集结了所有经验的“精品诚意之作”!
本文由站长之家用户投稿,未经站长之家同意,严禁转载。如广大用户朋友,发现稿件存在不实报道,欢迎读者反馈、纠正、举报问题()。
免责声明:本文为用户投稿的文章,站长之家发布此文仅为传递信息,不代表站长之家赞同其观点,不对对内容真实性负责,仅供用户参考之用,不构成任何投资、使用等行为的建议。请读者使用之前核实真实性,以及可能存在的风险,任何后果均由读者自行承担。如有发现
有好的文章希望站长之家帮助分享推广,猛戳这里
本网页浏览已超过3分钟,点击关闭或灰色背景,即可回到网页已收藏本页面
昨晚回到家倒了杯水坐在沙发上,亲戚的小孩在我家用网络机顶盒看动画片叫什么朵拉,里面正好在教英语what's
up,我只听见小妹妹跟着很大声的念:“卧槽,卧槽”,我一口水喷出来~
爱探险的朵拉!
你可能喜欢的图片笑话
最受欢迎的爆笑笑话
扫码下载糗事百科app鄙人不是专业做媒婆,只是工作需要大量对外交流,有机会就给圈内人拉拉线。网友不了解不方便介绍,实在抱歉。&br&&br&结婚早,婚后开始做媒婆,成功撮合很多对。口碑很好,会有男女请吃饭求介绍。&br&作为资深媒婆,与题主的感受相反,接受相亲的优秀女孩儿挺多的。她们不随便接受外人安排的相亲,更愿意托信任的圈内人寻觅。&br&我说的优秀是指女孩事业和性格都很不错,相貌也讨喜,生活中有不少追求者。她们大都工作做得风生水起,比较成熟,更喜欢主动争取,而不是简单在追求者中挑一个。&br&我给她们介绍对象,成功率惊人的高,一方面是条件确实好,另一方面是沟通能力强且头脑清晰。当然我会选择撮合三观和背景相契合的年轻人。有一次介绍的男生在北京工作,女生在上海,只是觉得特适合,忍不住搭个线。人家现在结婚了,依然异地,生活还处理得挺好,春节后可能同去杭州创业。&br&做十年媒婆,我发现最容易觅得佳偶的是24到30岁的女生,毕业后在职场历练过几年,事业开始稳定,头脑聪明思维清晰,没有不切实际的幻想。我给很漂亮但不太成熟的女生介绍过,没成功过,破坏我的口碑,再不给她介绍啦。&br&&br&有人问28岁或更大年龄好相亲吗?不是我吹,成功促成了两个大龄女神的婚姻,一位33岁,一位是36岁。33岁的那位姐姐,老公是我师兄,听我说了女方33岁后也爽快同意见面,他知道我绝没有胆子坑他!&br&36岁的那位姐姐是四婚,曾经嫁给同学,出国后离婚。国外嫁给华人后离婚。回国和一个乐队贝斯手结婚后离婚。恩,这样的姐姐我确实不敢介绍,但有个男神求我撮合啊。硬着头皮上,目前还挺好。两位姐姐的共同点是,有钱,有女人味。&br&&br&好的媒婆都是势利眼,你优秀,我就给你介绍优秀的。你不优秀,我就不给你介绍。
鄙人不是专业做媒婆,只是工作需要大量对外交流,有机会就给圈内人拉拉线。网友不了解不方便介绍,实在抱歉。 结婚早,婚后开始做媒婆,成功撮合很多对。口碑很好,会有男女请吃饭求介绍。 作为资深媒婆,与题主的感受相反,接受相亲的优秀女孩儿挺多的。她…
&p&果然是每逢佳节被逼亲。看的人还不少,我捋一下逻辑,突出下噱头。&br&&br&从大龄不靠谱男青年的角度,随便说说。&br&&br&1.相亲是有保底的,双向组织并购谈判行为。&br&&br&‘约会就是你不停用各种方法收集对方信息,直到你意识到已经喜欢上对方;相亲就是你带着批判地心态各种收集对方的缺点,然后当作和朋友聊天时的谈资。’&引自网络段子,出处不明&&br&&br&受压力或者裹挟,大部分人对待相亲,是不友好的,批判的,质疑的。但相亲至少会给你一次正式的展示自我机会,好好把握吧。&br&&br&那些态度不端正的,你呀好好想想,要是你自己搞来的号码,得要花多少心思,才能弄来第一次名正言顺的、从容不迫的、面对面的、360度全方位无死角的展示自我和了解对方的机会啊。&br&&br&a.而且跟谈恋爱不太一样的是,双方的意愿基本都会很明确主动。一般而言,需要在这一次见面中,形象化地建构自己的印象,了解对象的基本状况。&br&&br&比如,我的工作,家境,未来发展方向,消费情况,业余爱好,狐朋狗友类型,文艺音乐阅读的偏好。&br&了解对象的真实颜值、衣品、身高(如果很看重,请自觉多角度反ps滤镜式观察),谈吐等。&br&反正你最看重什么,就尽量友好的去知道答案,别模棱两可,最后耽误双方。&br&&br&b.还有一个“底”,是自己的底线。你务必想清楚自己的需求指标和自我状况。&br&&br&负面案例比如,跟某姑娘第三次见面时,走到一起发觉这姑娘太矮了,不喜欢。我了个去,你早干嘛去了!既然这么看重,直接把身高的匹配需求,重要性拉到第一条!在媒人介绍前,就可以快速筛选,获知结果。&br&&br&再比如诸多硬件不错的直男,对贤淑才艺之类软件层面的相当迷恋。那你直接跟媒人讲,我自己的财务状况大致怎样,但是我希望姑娘xxxx多少会化妆有眼缘,我自己有点闷工作略忙希望姑娘xxxxx不嫌弃xxxxx。&br&&br&这也是一轮筛选,三姑六婆和媒人,在推销她的委托对象时,也会通过她们自己的理解观念,来帮你拿捏。用电影.一句顶一万句.的话说,有媒人介绍的相亲,相对安心一点。&br&&br&c.哪些有的谈,哪些没的谈,尽量想明白,并且尽量告知媒人和相亲对象。&br&别搞得跟那个 为买房子谈得不愉快的萧山情侣 一样。把最看重的最难谈的东西,放在最前面。这不是恋爱,你猜你猜你猜猜,是谈判。&br&&br&比如我非常孝心,父母的意见我必须考量65%以上,这条没得谈。&br&比如我身高175,就是要找个168的,改造下后代。(我没写错!)&br&比如我极度讨厌虚荣的姑娘,三句不离‘我的朋友xxx牛逼’,‘xxx奢华荣耀’,这条没的谈。那你告知媒人务必要一个务实的,自己在聊天过招中,多观察。别搞得跟 那个程序员悲剧 一样,被套牢。&br&&br&--我知道,这条最难的,许多人列为前三条的需求很奇葩,而且自己心里想,还不好意思明说。&br&&br&d.想明白需求很重要,第一次见面很重要。&br&这条对直男加粗。&br&&br&别前面稀里糊涂,等见完面姑娘秒删之后,就各种追悔莫及。恋爱是由相识到相知,伴随荷尔蒙肾上腺素的加持,是有一定想象空间的。&br&&br&相亲没有这样的认识基础和想象空间,基本上第一次ko之后,就是路人了。&br&&br&当然如果你发疯了的看上对方了,你死缠烂打、动用各路媒人关系也是不可以,在姑娘没报警前,都有机会。&br&&br&e.还有需要强调的是,高质量的相亲,是建立在媒人靠谱的前提下的,如果你有相对明确量化的需求指标,其实可以挡住一大波 想在残留的宗亲文化中 刷存在感的三姑六婆二婶大姑父。&br&&br&&br&&br&2.相亲也是有约定俗成的规则的,跟谈恋爱不太一样。&br&一般而言,大致是媒人介绍相互加联系方式——寒暄几句第一次见面——相互告知第一印象,然后决定后续发展走向——逐渐深入沟通相互最关心的问题——确定正式交往并实时通报媒人或父母双方……&br&&br&这里面,对于后来者需要强调几点:&br&&br&a.第一次见面前,别瞎聊,别深聊。&br&&br&大家都心知肚明,直奔主题,寒暄几句之后,约定见面时间地点。有许多血淋淋的案例是,见面前百般心思讨好,聊出了天女散花,结果见完面,人家姑娘跑了,被各种花式指标秒杀,身高,颜值,车子,谈吐,各种都有。所以,正式见面前,别瞎聊,照片有假,媒人介绍的话也不靠谱。&br&&br&b.第一次见面当中,姑娘对你有兴趣的表现,有撩头发,会心的笑,主动式交谈等等。对你有敌意的表现为,问你家境年薪身高等各种指标化考核式的问题,一般过关斩将之后,看你表现。&br&&br&这条其实也有点玄学,因为大部分国人比较含蓄。但是如果遇到花式离场,请自觉收敛口水和企图心。&br&&br&比如:&br&很巧地碰到闺蜜朋友,要去跟着逛街。&br&xx疼xx病,要xxx回去。&br&领导安排xx项目,要去加班xxx忙。&br&阿姨来电老妈来电。&br&&br&c.一般而言,见完面之后,你需要明确地告知对方,你对她的印象,以及是否想继续深入了解的意愿。&br&--这是相亲,不是恋爱,需要揣摩暧昧虐心。&br&&br&但姑娘没有明确表达对你的印象,而回复不及时,且极度简短,代表你没能引起她兴趣,基本没戏。&br&----此条对直男加粗!!!&br&&br&&br&d.之所以一直强调“组织并购”,在于相亲中参与主体是你和姑娘,但参与人还有很多。所以相亲完,觉得这人ok,这个ok需要慎重。&br&因为之后到结婚的时间过程,你基本上会被媒人或者父母给加持,或者绑架。“你们都谈这么久了,啥时结婚那”,“都看对眼了,还在聊什么呢”,还是那句话,这是相亲,是有目的、直截了当、高效率、桌子上摊开摆明了的,组织并购行为。&br&&br&e.如果看不上,尽量委婉地告知媒人。没错,直接明确地告知对方,你看上或觉得哪里不合适。但相对委婉地告知媒人。虽然有唐突的嫌疑,但媒人也是在自己的世界观里做着好事,她们也是在帮你,如果这次不愉快,没有下次了。委婉的核心在于,不是人家不好,也不是你不好,而是不合适。&br&别瞎jb说人家姑娘xxxxx,媒人心想,我好心思将我最好的xxx的女儿介绍给你,你还xxxx。当然,你跟那一层亲戚有仇完全无视任何人,或者极度消极对抗相亲,那没关系。&br&&br&f.相亲中,重点是需求指标的匹配,所谓(恋)爱的感觉基本可以忽略。&br&--就是先结婚再谈恋爱。人是有感情的动物,只要在你的及格线内,你有的是时间培养感情。&br&但是话聊不聊的来,其实你心知肚明,在于你看中感觉层面的什么。相同爱好,三观?爱好这个评判不太好拿捏,是个女的,都会说喜欢旅游美食电影。三观就更不容易了。&br&看评论有人敏感,就再瞎掰几句。这里不是忽视感觉,而是指不要以追求那种霓虹国电影里手抖得厉害,心跳出来那种真命天女的恋爱感觉。以这种感觉为考核指标,去处相亲,基本上几率非常非常小。&br&感觉因为变化无常,模糊不定,其实某种程度上,是带有自我习得性经验的某种预测或偏见。想必男生还好一点,女生如果自己拿捏不准,找个可以敞开心窝,说心里话的参考人,别被感觉套着走。&br&&br&g.相亲难免尬聊,一般是男的需要找话题。&br&但有些姑娘看着很笨,不怎么会聊天,但无论当面还是微信,从头到尾都是主动式的聊天,请好好珍惜。所谓主动式的聊天,就是每一个回合,都不自觉地主动分享自己的感受或经历。并且对你的感受或者经历,表现出一定的兴趣。反例就是回复简单,信息明确。比如:&br&‘你晚上一般做什么?’&br&‘刷刷微博,看看韩剧,+表情’&br&同样信息,主动式:&br&‘这几天再看xxx,那个xx好二啊,我xxxx’,&br&‘哦,我偶尔还会刷刷微博,你应该xxxxxx吧’。&br&--这玩意讲深了就是玄学,好好珍惜吧,撞上狗屎运的家伙。&br&&br&h.有人看再来瞎掰。&/p&
果然是每逢佳节被逼亲。看的人还不少,我捋一下逻辑,突出下噱头。 从大龄不靠谱男青年的角度,随便说说。 1.相亲是有保底的,双向组织并购谈判行为。 ‘约会就是你不停用各种方法收集对方信息,直到你意识到已经喜欢上对方;相亲就是你带着批判地心态各种收…
beams,beauty youth,NANO UNIVERSE,SHIPS,rageblue,URBAN RESEARCH,JOURNAL STANDARD,ABAHOUSE,hare,adam et rope,global work,ciaopanic,wego,FREAK'S STORE,JUNred,JUNMEN,azul by moussy,coen,COMME CA COMMUNE,niko and...,MONKEY TIME,united arrows,GREEN LABEL RELAXING
beams,beauty youth,NANO UNIVERSE,SHIPS,rageblue,URBAN RESEARCH,JOURNAL STANDARD,ABAHOUSE,hare,adam et rope,global work,ciaopanic,wego,FREAK'S STORE,JUNred,JUNMEN,azul by moussy,coen,COMME CA COMMUNE,niko and...,MONKEY …
&p&Life is short, you need Python&/p&&p&人生苦短,我用Python&/p&&p&— Bruce Eckel&/p&&h2&&b&5.1 Python简介&/b&&/h2&&p&本章将介绍Python的最基本语法,以及一些和深度学习还有计算机视觉最相关的基本使用。&/p&&h2&&b&5.1.1 Python简史&/b&&/h2&&p&Python是一门解释型的高级编程语言,特点是简单明确。Python作者是荷兰人Guido van Rossum,1982年他获得数学和计算机硕士学位后,在荷兰数学与计算科学研究所( &b&C&/b& entrum &b&W&/b& iskunde & &b&I&/b& nformatica, &b&CWI&/b& )谋了份差事。在CWI期间,Guido参与到了一门叫做ABC的语言开发工作中。ABC是一门教学语言,所以拥有简单,可读性好,语法更接近自然语言等特点。在那个C语言一统天下的年代,ABC就是一股简单的清流,毕竟是门教学语言,最后没有流行起来,不过这段经历影响了Guido。1989年的圣诞假期,闲得蛋疼的Guido决定设计一门简单易用的新语言,要介于C和Shell之间,同时吸取ABC语法中的优点。Guido用自己喜欢的一部喜剧电视剧来命名这门语言:《Monty &b&Python&/b& ‘s Flying Circus》。&/p&&p&1991年,第一版基于C实现的Python编译器诞生,因为简单,拓展性好,Python很快就在Guido的同事中大受欢迎,不久Python的核心开发人员就从Guido一人变成了一个小团队。后来随着互联网时代的到来,开源及社区合作的方式蓬勃发展,Python也借此上了发展的快车道。因为Python非常容易拓展,在不同领域的开发者贡献下,许多受欢迎的功能和特征被开发出来,渐渐形成了各种各样的库,其中一部分被加入到Python的标准库中,这让本来就不需要过多思考底层细节的Python变得更加强大好用。在不过多考虑执行效率的前提下,使用Python进行开发的周期相比传统的C/C++甚至Java等语言都大大缩短,代码量也大幅降低,所以出bug的可能性也小了很多。因此有了语言专家Bruce Eckel的那句名言:Life is short, you need Python. 后来这句话的中文版“人生苦短,我用Python”被Guido印在了T恤上。发展至今,Python渐渐成了最流行的语言之一,在编程语言排行榜TOBIE中常年占据前5的位置。另外随着Python的用户群越来越壮大,慢慢在本身特点上发展出了自己的哲学,叫做Python的禅(The Zen of Python)。遵循Python哲学的做法叫做很Python(Pythonic),具体参见:&/p&&p&&a href=&//link.zhihu.com/?target=https%3A//www.python.org/dev/peps/pep-0020/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&PEP 20 — The Zen of Python&/a&&/p&&p&或者在Python中执行:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&& import this
&/code&&/pre&&/div&&p&Python拥有很好的扩充性,可以非常轻松地用其他语言编写模块供调用,用Python编写的模块也可以通过各种方式轻松被其他语言调用。所以一种常见的Python使用方式是,底层复杂且对效率要求高的模块用C/C++等语言实现,顶层调用的API用Python封装,这样可以通过简单的语法实现顶层逻辑,故而Python又被称为“胶水语言”。这种特性的好处是,无需花费很多时间在编程实现上,更多的时间可以专注于思考问题的逻辑。尤其是对做算法和深度学习的从业人员,这种方式是非常理想的,所以如今的深度学习框架中,除了MATLAB,或是Deeplearning4j这种摆明了给Java用的,其他框架基本上要么官方接口就是Python,要么支持Python接口。&/p&&h2&&b&5.1.2 安装和使用Python&/b&&/h2&&p&Python有两个大版本,考虑到用户群数量和库的各种框架的兼容性,本文以Python2(2.7)为准,语法尽量考虑和Python3的兼容。&/p&&p&Unix/Linux下的Python基本都是系统自带的,一般默认为Python2,使用时在终端直接键入python就能进入Python解释器界面:&/p&&p&&br&&/p&&p&&br&&/p&&p&在解释器下就已经可以进行最基本的编程了,比如:&/p&&p&&br&&/p&&p&&br&&/p&&p&写程序的话还是需要保存成文件再执行,比如我们写下面语句,并且保存为helloworld.py:&/p&&p&&b&print&/b& &b&(&/b& “Hello world!” &b&)&/b&&/p&&p&然后在终端里执行:&/p&&p&&br&&/p&&p&&br&&/p&&p&安装更多的python库一般有两种方法,第一是用系统的软件包管理,以Ubuntu 16.04 LTS为例,比如想要安装numpy库(后面会介绍这个库),软件包的名字就是python-numpy,所以在终端中输入:&/p&&p&&& sudo apt install python-numpy&/p&&p&Python自己也带了包管理器,叫做pip,使用如下:&/p&&p&&& pip install numpy&/p&&p&安装和深度学习相关的框架时,一般来说推荐使用系统自带的包管理,出现版本错误的可能性低一些。另外也可以使用一些提前配置好很多第三方库的Python包,这些包通常已经包含了深度学习框架中绝大多数的依赖库,比如最常用的是Anaconda:&/p&&p&&a href=&//link.zhihu.com/?target=https%3A//www.continuum.io/downloads& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Download Anaconda Now!&/a&&/p&&p&Windows下的Python安装简单一些,从官方网站下载相应的安装程序就可以了,当然也有更方便的已经包含了很全的第三方库的选择,WinPython:&/p&&p&&a href=&//link.zhihu.com/?target=http%3A//winpython.github.io/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&WinPython&/a&&/p&&p&并且是绿色的,直接执行就可以用了。&/p&&h2&&b&5.2 Python基本语法&/b&&/h2&&p&There should be one– and preferably only one –obvious way to do it.&/p&&p&对于一个特定的问题,应该只用最好的一种方法来解决。&/p&&p&— Tim Peters&/p&&h2&&b&5.2.1 基本数据类型和运算&/b&&/h2&&h2&&b&基本数据类型&/b&&/h2&&p&Python中最基本的数据类型包括整型,浮点数,布尔值和字符串。类型是不需要声明的,比如:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = 1
# 布尔类型
d = &False& # 字符串
# NoneType
&/code&&/pre&&/div&&p&其中#是行内注释的意思。最后一个None是NoneType,注意不是0,在Python中利用type函数可以查看一个变量的类型:&/p&&div class=&highlight&&&pre&&code class=&language-text&&type(a)
# &type 'int'&
# &type 'float'&
# &type 'bool'&
# &type 'str'&
# &type 'NoneType'&
&/code&&/pre&&/div&&p&注释中是执行type()函数后的输出结果,可以看到None是单独的一种类型NoneType。在很多API中,如果执行失败就会返回None。&/p&&h2&&b&变量和引用&/b&&/h2&&p&Python中基本变量的赋值一般建立的是个引用,比如下面的语句:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = 1
&/code&&/pre&&/div&&p&a赋值为1后,b=a执行时并不会将a的值复制一遍,然后赋给b,而是简单地为a所指的值,也就是1建立了一个引用,相当于a和b都是指向包含1这个值的这块内存的指针。所以c=1执行的也是个引用建立,这三个变量其实是三个引用,指向同一个值。这个逻辑虽然简单,不过也还是常常容易弄混,这没关系,Python内置了id函数,可以返回一个对象的地址,用id函数可以让我们知道每个变量指向的是不是同一个值:&/p&&div class=&highlight&&&pre&&code class=&language-text&&id(a)
&/code&&/pre&&/div&&p&注释中表示的仍是执行后的结果。如果这时候我们接下面两个语句:&/p&&div class=&highlight&&&pre&&code class=&language-text&&b = 2
# b的引用到新的一个变量上
&/code&&/pre&&/div&&p&可以看到b引用到了另一个变量上。&/p&&h2&&b&运算符&/b&&/h2&&p&Python中的数值的基本运算和C差不多,字符串的运算更方便,下面是常见的例子:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = 2
# 2 + 2.3 = 4.3
# 3 - 2 = 1
# 整数除以浮点数,运算以浮点数为准,2 / 2.3 = 0.3044
# Python2中,整数除法,向下取整 2 / 3 = 0
# a的c次方,结果为8
# Python中没有i++的用法,自增用+=
# c变成0了
d = 'Hello'
d + ' world!'
# 相当于字符串拼接,结果为'Hello world!'
d += ' &world&!'# 相当于把字符串接在当前字符串尾,d变为'Hello &world&!'
e = r'\n\t\\'
# '\\n\\t\\\\'
&/code&&/pre&&/div&&p&需要提一下的几点:1)字符串用双引号和单引号都可以,区别主要是单引号字符串中如果出现单引号字符则需要用转义符,双引号也是一样,所以在单引号字符串中使用双引号,或者双引号字符串中使用单引号就会比较方便。另外三个双引号或者三个单引号围起来的也是字符串,因为换行方便,更多用于文档。2)Python2中两个数值相除会根据数值类型判断是否整数除法,Python3种则都按照浮点数。想要在Python2种也执行Python3中的除法只要执行下面语句:&/p&&div class=&highlight&&&pre&&code class=&language-text&&from __future__ import division
# 使用Python3中的除法
&/code&&/pre&&/div&&p&3)字符串前加r表示字符串内容严格按照输入的样子,好处是不用转义符了,非常方便。&/p&&p&Python中的布尔值和逻辑的运算非常直接,下面是例子:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = True
&/code&&/pre&&/div&&p&基本上就是英语,操作符优先级之类的和其他语言类似。Python中也有位操作:&/p&&div class=&highlight&&&pre&&code class=&language-text&&~8
# 按位翻转,1000 --& -(1000+1)
# 右移3位,1000 --& 0001
# 左移3位,0001 --& 1000
# 按位与,101 & 010 = 000
# 按位或,101 | 010 = 111
# 按位异或,100 ^ 001 = 101
&/code&&/pre&&/div&&p&==, != &b&和is&/b&&/p&&p&判断是否相等或者不等的语法和C也一样,另外在Python中也常常见到is操作符,这两者的区别在于==和!=比较引用指向的内存中的内容,而is判断两个变量是否指向一个地址,看下面的代码例子:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = 1
# True,值相等
# False,指向的不是一个对象,这个语句等效于 id(a) == id(b)
# True,指向的都是整型值1
&/code&&/pre&&/div&&p&所以一定要分清要比较的对象应该用那种方式,对于一些特殊的情况,比如None,本着Pythonic的原则,最好用is None。&/p&&h2&&b&注意关键字&/b&&/h2&&p&Python中,万物皆对象。不过这并不是这里要探讨的话题,想说的是一定要注意关键字,因为所有东西都是对象,所以一个简简单单的赋值操作就可以把系统内置的函数给变成一个普通变量,来看下边例子:&/p&&div class=&highlight&&&pre&&code class=&language-text&&id(type)
# type成了指向1的变量
# id成了指向2的变量
from __future__ import print_function
# print成了指向3的变量
&/code&&/pre&&/div&&p&注意print是个很特殊的存在,在Python3中是按照函数用,在Python2中却是个命令式的语句,最早print的用法其实是下边这样:&/p&&div class=&highlight&&&pre&&code class=&language-text&&print &Hello world!&
&/code&&/pre&&/div&&p&这么用主要是受到ABC语法的影响,但这个用法并不Pythonic,后来加入了print函数,为了兼容允许两种用法并存。所以单纯给print赋值是不灵的,在Python2中使用Python3中的一些特性都是用from __future__ import来实现。&/p&&h2&&b&模块导入&/b&&/h2&&p&因为提到了对象名覆盖和import,所以简单讲一下。import是利用Python中各种强大库的基础,比如要计算cos(π)的值,可以有下面4种方式:&/p&&div class=&highlight&&&pre&&code class=&language-text&&# 直接导入Python的内置基础数学库
import math
print(math.cos(math.pi))
# 从math中导入cos函数和pi变量
from math import cos, pi
print(cos(pi))
# 如果是个模块,在导入的时候可以起个别名,避免名字冲突或是方便懒得打字的人使用
import math as m
print(m.cos(m.pi))
# 从math中导入所有东西
from math import *
print(cos(pi))
&/code&&/pre&&/div&&p&一般来说最后一种方式不是很推荐,因为不知道import导入的名字里是否和现有对象名已经有冲突,很可能会不知不觉覆盖了现有的对象。&/p&&h2&&b&5.2.2 容器&/b&&/h2&&p&&b&列表&/b&&/p&&p&Python中的容器是异常好用且异常有用的结构。这节主要介绍列表(list),元组(tuple),字典(dict)和集合(set)。这些结构和其他语言中的类似结构并无本质不同,来看例子了解下使用:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = [1, 2, 3, 4]
e = [1, &Hello world!&, c, False]
print(id(b), id(c))
print(id(b), id(d))
print(b == c)
f = list(&abcd&)
# ['a', 'b', 'c', 'd']
g = [0]*3 + [1]*4 + [2]*2
# [0, 0, 0, 1, 1, 1, 1, 2, 2]
&/code&&/pre&&/div&&p&因为变量其实是个引用,所以对列表而言也没什么不同,所以列表对类型没什么限制。也正因为如此,和变量不同的是,即使用相同的语句赋值,列表的地址也是不同的,在这个例子中体现在id(b)和id(c)不相等,而内容相等。列表也可以用list()初始化,输入参数需要是一个可以遍历的结构,其中每一个元素会作为列表的一项。“*”操作符对于列表而言是复制,最后一个语句用这种办法生成了分段的列表。&/p&&p&列表的基本操作有访问,增加,删除,和拼接:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a.pop()
# 把最后一个值4从列表中移除并作为pop的返回值
a.append(5)
# 末尾插入值,[1, 2, 3, 5]
a.index(2)
# 找到第一个2所在的位置,也就是1
# 取下标,也就是位置在2的值,也就是第三个值3
a += [4, 3, 2]
# 拼接,[1, 2, 3, 5, 4, 3, 2]
a.insert(1, 0)
# 在下标为1处插入元素0,[1, 0, 2, 3, 5, 4, 3, 2]
a.remove(2)
# 移除第一个2,[1, 0, 3, 5, 4, 3, 2]
a.reverse()
# 倒序,a变为[2, 3, 4, 5, 3, 0, 1]
# 指定下标处赋值,[2, 3, 4, 9, 3, 0, 1]
b = a[2:5]
# 取下标2开始到5之前的子序列,[4, 9, 3]
c = a[2:-2]
# 下标也可以倒着数,方便算不过来的人,[4, 9, 3]
# 取下标2开始到结尾的子序列,[4, 9, 3, 0, 1]
# 取开始到下标5之前的子序列,[2, 3, 4, 9, 3]
# 取从开头到最后的整个子序列,相当于值拷贝,[2, 3, 4, 9, 3, 0, 1]
a[2:-2] = [1, 2, 3] # 赋值也可以按照一段来,[2, 3, 1, 2, 3, 0, 1]
g = a[::-1]
# 也是倒序,通过slicing实现并赋值,效率略低于reverse()
# 列表内排序,a变为[0, 1, 1, 2, 2, 3, 3]
&/code&&/pre&&/div&&p&因为列表是有顺序的,所以和顺序相关的操作是列表中最常见的,首先我们来打乱一个列表的顺序,然后再对这个列表排序:&/p&&div class=&highlight&&&pre&&code class=&language-text&&import random
a = range(10)
# 生成一个列表,从0开始+1递增到9
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
random.shuffle(a)
# shuffle函数可以对可遍历且可变结构打乱顺序
# [4, 3, 8, 9, 0, 6, 2, 7, 5, 1]
b = sorted(a)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
c = sorted(a, reverse=True)
# [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
&/code&&/pre&&/div&&p&&b&元组&/b&&/p&&p&元组和列表有很多相似的地方,最大的区别在于不可变,还有如果初始化只包含一个元素的tuple和列表不一样,因为语法必须明确,所以必须在元素后加上逗号。另外直接用逗号分隔多个元素赋值默认是个tuple,这在函数多返回值的时候很好用:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = (1, 2)
b = tuple(['3', 4]) # 也可以从列表初始化
e = 3, 4, 5
# (3, 4, 5)
&/code&&/pre&&/div&&p&&b&集合&/b&&/p&&p&集合是一种很有用的数学操作,比如列表去重,或是理清两组数据之间的关系,集合的操作符和位操作符有交集,注意不要弄混:&/p&&div class=&highlight&&&pre&&code class=&language-text&&A = set([1, 2, 3, 4])
B = {3, 4, 5, 6}
C = set([1, 1, 2, 2, 2, 3, 3, 3, 3])
# 集合的去重效果,set([1, 2, 3])
print(A | B)
# 求并集,set([1, 2, 3, 4, 5, 6])
print(A & B)
# 求交集,set([3, 4])
print(A - B)
# 求差集,属于A但不属于B的,set([1, 2])
print(B - A)
# 求差集,属于B但不属于A的,set([5, 6])
print(A ^ B)
# 求对称差集,相当于(A-B)|(B-A),set([1, 2, 5, 6])
&/code&&/pre&&/div&&p&&b&字典&/b&&/p&&p&字典是一种非常常见的“键-值”( &b&k&/b& ey- &b&v&/b& alue)映射结构,键无重复,一个键不能对应多个值,不过多个键可以指向一个值。还是通过例子来了解,构建一个名字-&年龄的字典,并执行一些常见操作:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = {'Tom': 8, 'Jerry': 7}
print(a['Tom'])
b = dict(Tom=8, Jerry=7)
# 一种字符串作为键更方便的初始化方式
print(b['Tom'])
if 'Jerry' in a:
# 判断'Jerry'是否在keys里面
print(a['Jerry'])
print(a.get('Spike'))
# None,通过get获得值,即使键不存在也不会报异常
a['Spike'] = 10
a['Tyke'] = 3
a.update({'Tuffy': 2, 'Mammy Two Shoes': 42})
print(a.values())
# dict_values([8, 2, 3, 7, 10, 42])
print(a.pop('Mammy Two Shoes'))
# 移除'Mammy Two Shoes'的键值对,并返回42
print(a.keys())
# dict_keys(['Tom', 'Tuffy', 'Tyke', 'Jerry', 'Spike'])
&/code&&/pre&&/div&&p&注意到初始化字典和集合很像,的确如此,集合就像是没有值只有键的字典。既然有了人名到年龄的映射,也许你立马想到是否可以给字典排序?在Python3.6之前,这个问题是错误的,字典是一种映射关系,没有顺序。当然了,如果要把(键, 值)的这种对进行排序,是没有问题的,前提是先把字典转化成可排序的结构,items()或者iteritems()可以做到这件事,接上段代码继续:&/p&&div class=&highlight&&&pre&&code class=&language-text&&b = a.items()
# [('Tuffy', 2), ('Spike', 10), ('Tom', 8), ('Tyke', 3), ('Jerry', 7)]
from operator import itemgetter
c = sorted(a.items(), key=itemgetter(1))
# [('Tuffy', 2), ('Tyke', 3), ('Jerry', 7), ('Tom', 8), ('Spike', 10)]
d = sorted(a.iteritems(), key=itemgetter(1))
# [('Tuffy', 2), ('Tyke', 3), ('Jerry', 7), ('Tom', 8), ('Spike', 10)]
e = sorted(a)
# 只对键排序,['Jerry', 'Spike', 'Tom', 'Tuffy', 'Tyke']
&/code&&/pre&&/div&&p&items()可以把字典中的键值对转化成一个列表,其中每个元素是一个tuple,tuple的第一个元素是键,第二个元素是值。变量c是按照值排序,所以需要一个操作符itemgetter,去位置为1的元素作为排序参考,如果直接对字典排序,则其实相当于只是对键排序。字典被当作一个普通的可遍历结构使用时,都相当于遍历字典的键。如果觉得字典没有顺序不方便,可以考虑使用OrderedDict,使用方式如下:&/p&&div class=&highlight&&&pre&&code class=&language-text&&from collections import OrderedDict
a = {1: 2, 3: 4, 5: 6, 7: 8, 9: 10}
b = OrderedDict({1: 2, 3: 4, 5: 6, 7: 8, 9: 10})
# {1: 2, 3: 4, 9: 10, 5: 6, 7: 8}
# OrderedDict([(1, 2), (3, 4), (9, 10), (5, 6), (7, 8)])
&/code&&/pre&&/div&&p&这样初始化时的顺序就保留了,除了有序的特性以外,用法上和字典没有区别。2016年9月,Guido宣布在Python3.6中,字典将默认有序,这样就不用纠结了。另外需要注意的一点是字典是通过哈希表实现的,所以键必须是可哈希的, list不能被哈希,所以也不能作为字典的键,而tuple就可以。&/p&&p&因为上上段代码中用到了iteritems(),所以这里顺带提一下迭代器(iterator),迭代器相当于一个函数,每次调用都返回下一个元素,从遍历的角度来看就和列表没有区别了。iteritems()就是一个迭代器,所以效果一样,区别是迭代器占用更少内存,因为不需要一上来就生成整个列表。一般来说,如果只需要遍历一次,用迭代器是更好的选择,若是要多次频繁从一个可遍历结构中取值,且内存够,则直接生成整个列表会更好。当然,用迭代器生成一个完整列表并不麻烦,所以有个趋势是把迭代器作为默认的可遍历方式,比如前面我们使用过用来生成等差数列列表的range(),在Python2中对应的迭代器形式是xrange()。在Python3中,range()就不再产生一个列表了,而是作为迭代器,xrange()直接没了。&/p&&h2&&b&5.2.3 分支和循环&/b&&/h2&&p&从这节开始,代码就未必适合在Python终端中输入了,选个顺手的编辑器或者IDE。作者良心推荐PyCharm,虽然慢,但好用,社区版免费:&/p&&p&&a href=&//link.zhihu.com/?target=https%3A//www.jetbrains.com/pycharm/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&PyCharm&/a&&/p&&p&&b&for循环&/b&&/p&&p&上面提到的4种容器类型都是可遍历的,所以该讲讲用来遍历的for循环了。for循环的语法也是简单的英语:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = ['This', 'is', 'a', 'list', '!']
b = ['This', 'is', 'a', 'tuple', '!']
c = {'This': 'is', 'an': 'unordered', 'dict': '!'}
# 依次输出:'This', 'is', 'a', 'list', '!'
for x in a:
# 依次输出:'This', 'is', 'a', 'tuple', '!'
for x in b:
# 键的遍历。不依次输出:'This', 'dict', 'an'
for keyin c:
print(key)
# 依次输出0到9
for i in range(10):
&/code&&/pre&&/div&&p&注意到每个for循环中,print都有缩进,这是Python中一个让人爱恨交织的特点: &b&强行缩进&/b& 来表明成块的代码。这样做的好处是代码十分清晰工整,还有助于防止写出过长的函数或者过深的嵌套,坏处是有时候不知为什么tab和空格就一起出现了,又或是多重if-else不知怎得就没对齐,还是挺麻烦的。&/p&&p&回到for循环上,这种把每个元素拿出来的遍历方式叫做for_each风格,熟悉Java的话就不会陌生,C++11中也开始支持这种for循环方式。不过如果还是需要下标呢?比如遍历一个list的时候,希望把对应下标也打印出来,这时可以用enumerate:&/p&&div class=&highlight&&&pre&&code class=&language-text&&names = [&Rick&, &Daryl&, &Glenn&]
# 依次输出下标和名字
for i, namein enumerate(names):
print(i, name)
&/code&&/pre&&/div&&p&需要注意的是,通过取下标遍历当然是可行的,比如用len()函数获得列表长度,然后用range()/xrange()函数获得下标,但是并不推荐这样做:&/p&&div class=&highlight&&&pre&&code class=&language-text&&words = [&This&, &is&, &not&, &recommended&]
# not pythonic :(
for i in xrange(len(words)):
print(words[i])
&/code&&/pre&&/div&&p&在使用for循环时,有时会遇到这样一种场景:我们需要对遍历的每个元素进行某种判断,如果符合这种判断的情况没有发生,则执行一个操作。举个例子某神秘部门要审核一个字符串列表,如果没有发现不和谐的字眼,则将内容放心通过,一种解决办法是下面这样:&/p&&div class=&highlight&&&pre&&code class=&language-text&&wusuowei = [&I&, &don't&, &give&, &a&, &shit&]
hexie = True
# 默认和谐社会
for x in wusuowei:
if x == &f**k&:
print(&What the f**k!&)
# 发现了不该出现的东西,WTF!
hexie = False
# 不和谐了
# 赶紧停下!不能再唱了
# 未发现不和谐元素!
print(&Harmonious society!&)
# 和谐社会!
&/code&&/pre&&/div&&p&这样需要设置一个标记是否发现不和谐因素的状态变量hexie,循环结束后再根据这个变量判断内容是否可以放心通过。一种更简洁不过有些小众的做法是直接和else一起,如果for循环中的if块内的语句没有被触发,则通过else执行指定操作:&/p&&div class=&highlight&&&pre&&code class=&language-text&&wusuowei = [&I&, &don't&, &give&, &a&, &shit&]
for x in wusuowei:
if x == &f**k&:
print(&What the f**k!&)
hexie = False
# for循环中if内语句未被触发
print(&Harmonious society!&) # 和谐社会!
&/code&&/pre&&/div&&p&这样不需要一个标记是否和谐的状态变量,语句简洁了很多。&/p&&p&if &b&和分支结构&/b&&/p&&p&上一个例子中已经出现if语句了,所以这部分讲讲if。Python的条件控制主要是三个关键字:if-elif-else,其中elif就是else if的意思。还是看例子:&/p&&div class=&highlight&&&pre&&code class=&language-text&&pets =['dog', 'cat', 'droid', 'fly']
for petin pets:
if pet == 'dog':
food = 'steak'
elif pet == 'cat':
food = 'milk'
elif pet == 'droid':
food = 'oil'
elif pet == 'fly':
food = 'sh*t'
print(food)
&/code&&/pre&&/div&&p&需要提一下的是pass,这就是个空语句,什么也不做,占位用。Python并没有switch-case的语法,等效的用法要么是像上面一样用if-elif-else的组合,要么可以考虑字典:&/p&&div class=&highlight&&&pre&&code class=&language-text&&pets = ['dog', 'cat', 'droid', 'fly']
food_for_pet = {
'dog': 'steak',
'cat': 'milk',
'droid': 'oil',
'fly': 'sh*t'
for petin pets:
food = food_for_pet[pet] if petin food_for_petelse None
print(food)
&/code&&/pre&&/div&&p&这里还用到了一个if-else常见的行内应用,就是代替三元操作符,如果键在字典中,则food取字典的对应值,否则为None。&/p&&p&if &b&表达式中的小技巧&/b&&/p&&p&通过链式比较让语句简洁:&/p&&div class=&highlight&&&pre&&code class=&language-text&&if -1 & x & 1:
# 相较于 if x & -1 and x & 1:
print('The absolute value of x is & 1')
&/code&&/pre&&/div&&p&判断一个值是不是等于多个可能性中的一个:&/p&&div class=&highlight&&&pre&&code class=&language-text&&if x in ['piano', 'violin', 'drum']:
# 相较于 if x == 'piano' or x == 'violin' or x =='drum':
print(&It's an instrument!&)
&/code&&/pre&&/div&&p&Python中的对象都会关联一个真值,所以在if表达式中判断是否为False或者是否为空的时候,是无需写出明确的表达式的:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = True
if a: # 判断是否为真,相较于 a is True
print('a is True')
if 'sky': # 判断是否空字符串,相较于 len('sky') & 0
print('birds')
if '': # 判断是否空字符串,同上
print('Nothing!')
if {}: # 判断是否空的容器(字典),相较于len({}) & 0
print('Nothing!')
&/code&&/pre&&/div&&p&隐式表达式为False的是如下状况:&/p&&p&– None&/p&&p&– False&/p&&p&– 数值0&/p&&p&– 空的容器或序列(字符串也是一种序列)&/p&&p&– 用户自定义类中,如果定义了__len__()或者__nonzero__(),并且被调用后返回0或者False&/p&&p&while &b&循环&/b&&/p&&p&while的就是循环和if的综合体,是一种单纯的基于条件的循环,本身没有遍历的意思,这是和for_each的本质差别,这种区别比起C/C++中要明确得多,用法如下:&/p&&div class=&highlight&&&pre&&code class=&language-text&&i = 0
while i & 100:
print(&ha&)
while True:
print(&ha&)
&/code&&/pre&&/div&&h2&&b&5.2.4 函数、生成器和类&/b&&/h2&&p&还是从几个例子看起:&/p&&div class=&highlight&&&pre&&code class=&language-text&&def say_hello():
print('Hello!')
def greetings(x='Good morning!'):
say_hello()
greetings()
# Good morning!
greetings(&What's up!&)
# What's up!
a = greetings()
# 返回值是None
def create_a_list(x, y=2, z=3): # 默认参数项必须放后面
return [x, y, z]
b = create_a_list(1)
# [1, 2, 3]
c = create_a_list(3, 3)
# [3, 3, 3]
d = create_a_list(6, 7, 8)
# [6, 7, 8]
def traverse_args(*args):
for argin args:
print(arg)
traverse_args(1, 2, 3)
# 依次打印1, 2, 3
traverse_args('A', 'B', 'C', 'D')
# 依次打印A, B, C, D
def traverse_kargs(**kwargs):
for k, v in kwargs.items():
print(k, v)
traverse_kargs(x=3, y=4, z=5)
# 依次打印('x', 3), ('y', 4), ('z', 5)
traverse_kargs(fighter1='Fedor', fighter2='Randleman')
def foo(x, y, *args, **kwargs):
print(x, y)
print(args)
print(kwargs)
# 第一个pring输出(1, 2)
# 第二个print输出(3, 4, 5)
# 第三个print输出{'a': 3, 'b': 'bar'}
foo(1, 2, 3, 4, 5, a=6, b='bar')
&/code&&/pre&&/div&&p&其实和很多语言差不多,括号里面定义参数,参数可以有默认值,且默认值不能在无默认值参数之前。Python中的返回值用return定义,如果没有定义返回值,默认返回值是None。参数的定义可以非常灵活,可以有定义好的固定参数,也可以有可变长的参数(args: arguments)和关键字参数(kargs: keyword arguments)。如果要把这些参数都混用,则固定参数在最前,关键字参数在最后。&/p&&p&Python中万物皆对象,所以一些情况下函数也可以当成一个变量似的使用。比如前面小节中提到的用字典代替switch-case的用法,有的时候我们要执行的不是通过条件判断得到对应的变量,而是执行某个动作,比如有个小机器人在坐标(0, 0)处,我们用不同的动作控制小机器人移动:&/p&&div class=&highlight&&&pre&&code class=&language-text&&moves = ['up', 'left', 'down', 'right']
coord = [0, 0]
for movein moves:
if move == 'up':
# 向上,纵坐标+1
coord[1] += 1
elif move == 'down':
# 向下,纵坐标-1
coord[1] -= 1
elif move == 'left':
# 向左,横坐标-1
coord[0] -= 1
elif move == 'right':
# 向右,横坐标+1
coord[0] += 1
print(coord)
&/code&&/pre&&/div&&p&不同条件下对应的是对坐标这个列表中的值的操作,单纯的从字典取值就办不到了,所以就把函数作为字典的值,然后用这个得到的值执行相应动作:&/p&&div class=&highlight&&&pre&&code class=&language-text&&moves = ['up', 'left', 'down', 'right']
def move_up(x):
# 定义向上的操作
def move_down(x):
# 定义向下的操作
def move_left(x):
# 定义向左的操作
def move_right(x):
# 定义向右的操作
# 动作和执行的函数关联起来,函数作为键对应的值
actions = {
'up': move_up,
'down': move_down,
'left': move_left,
'right': move_right
coord = [0, 0]
for movein moves:
actions[move](coord)
print(coord)
&/code&&/pre&&/div&&p&把函数作为值取到后,直接加一括号就能使了,这样做之后起码在循环部分看上去很简洁。有点C里边函数指针的意思,只不过更简单。其实这种用法在之前讲排序的时候我们已经见过了,就是operator中的itemgetter。itemgetter(1)得到的是一个可调用对象(callable object),和返回下标为1的元素的函数用起来是一样的:&/p&&div class=&highlight&&&pre&&code class=&language-text&&def get_val_at_pos_1(x):
return x[1]
('Superman', 99),
('Batman', 100),
('Joker', 85)
sorted_pairs0 = sorted(heros, key=get_val_at_pos_1)
sorted_pairs1 = sorted(heros, key=lambda x: x[1])
print(sorted_pairs0)
print(sorted_pairs1)
&/code&&/pre&&/div&&p&在这个例子中我们用到了一种特殊的函数:lambda表达式。Lambda表达式在Python中是一种匿名函数,lambda关键字后面跟输入参数,然后冒号后面是返回值(的表达式),比如上边例子中就是一个取下标1元素的函数。当然,还是那句话,万物皆对象,给lambda表达式取名字也是一点问题没有的:&/p&&div class=&highlight&&&pre&&code class=&language-text&&some_ops = lambda x, y: x + y + x*y + x**y
some_ops(2, 3)
# 2 + 3 + 2*3 + 2^3 = 19
&/code&&/pre&&/div&&p&生成器(Generator &b&)&/b&&/p&&p&生成器是迭代器的一种,形式上看和函数很像,只是把return换成了yield,在每次调用的时候,都会执行到yield并返回值,同时将当前状态保存,等待下次执行到yield再继续:&/p&&div class=&highlight&&&pre&&code class=&language-text&&# 从10倒数到0
def countdown(x):
while x &= 0:
for i in countdown(10):
# 打印小于100的斐波那契数
def fibonacci(n):
while b & n:
a, b = b, a + b
for x in fibonacci(100):
&/code&&/pre&&/div&&p&生成器和所有可迭代结构一样,可以通过next()函数返回下一个值,如果迭代结束了则抛出StopIteration异常:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = fibonacci(3)
print(next(a))
print(next(a))
print(next(a))
print(next(a))
# 抛出StopIteration异常
&/code&&/pre&&/div&&p&Python3.3以上可以允许yield和return同时使用,return的是异常的说明信息:&/p&&div class=&highlight&&&pre&&code class=&language-text&&# Python3.3以上可以return返回异常的说明
def another_fibonacci(n):
while b & n:
a, b = b, a + b
return &No more ...&
a = another_fibonacci(3)
print(next(a))
print(next(a))
print(next(a))
print(next(a))
# 抛出StopIteration异常并打印No more消息
&/code&&/pre&&/div&&p&类(Class &b&)&/b&&/p&&p&Python中的类的概念和其他语言相比没什么不同,比较特殊的是protected和private在Python中是没有明确限制的,一个惯例是用单下划线开头的表示protected,用双下划线开头的表示private:&/p&&div class=&highlight&&&pre&&code class=&language-text&&class A:
&&&Class A&&&
def __init__(self, x, y, name):
self.x = x
self.y = y
self._name = name
def introduce(self):
print(self._name)
def greeting(self):
print(&What's up!&)
def __l2norm(self):
return self.x**2 + self.y**2
def cal_l2norm(self):
return self.__l2norm()
a = A(11, 11, 'Leonardo')
print(A.__doc__)
# &Class A&
a.introduce()
# &Leonardo&
a.greeting()
# &What's up!&
print(a._name)
# 可以正常访问
print(a.cal_l2norm())
# 输出11*11+11*11=242
print(a._A__l2norm())
# 仍然可以访问,只是名字不一样
print(a.__l2norm())
# 报错: 'A' object has no attribute '__l2norm'
&/code&&/pre&&/div&&p&类的初始化使用的是__init__(self,),所有成员变量都是self的,所以以self.开头。可以看到,单下划线开头的变量是可以直接访问的,而双下划线开头的变量则触发了Python中一种叫做name mangling的机制,其实就是名字变了下,仍然可以通过前边加上“_类名”的方式访问。也就是说Python中变量的访问权限都是靠自觉的。类定义中紧跟着类名字下一行的字符串叫做docstring,可以写一些用于描述类的介绍,如果有定义则通过“类名.__doc__”访问。这种前后都加双下划线访问的是特殊的变量/方法,除了__doc__和__init__还有很多,这里就不展开讲了。&/p&&p&Python中的继承也非常简单,最基本的继承方式就是定义类的时候把父类往括号里一放就行了:&/p&&div class=&highlight&&&pre&&code class=&language-text&&class B(A):
&&&Class B inheritenced from A&&&
def greeting(self):
print(&How's going!&)
b = B(12, 12, 'Flaubert')
b.introduce()
# Flaubert
b.greeting()
# How's going!
print(b._name())
# Flaubert
print(b._A__l2norm())
# “私有”方法,必须通过_A__l2norm访问
&/code&&/pre&&/div&&h2&&b&5.2.5 map, reduce和filter&/b&&/h2&&p&map可以用于对可遍历结构的每个元素执行同样的操作,批量操作:&/p&&div class=&highlight&&&pre&&code class=&language-text&&map(lambda x: x**2, [1, 2, 3, 4])
# [1, 4, 9, 16]
map(lambda x, y: x + y, [1, 2, 3], [5, 6, 7])
# [6, 8, 10]
&/code&&/pre&&/div&&p&reduce则是对可遍历结构的元素按顺序进行两个输入参数的操作,并且每次的结果保存作为下次操作的第一个输入参数,还没有遍历的元素作为第二个输入参数。这样的结果就是把一串可遍历的值,减少(reduce)成一个对象:&/p&&div class=&highlight&&&pre&&code class=&language-text&&reduce(lambda x, y: x + y, [1, 2, 3, 4])
# ((1+2)+3)+4=10
&/code&&/pre&&/div&&p&filter顾名思义,根据条件对可遍历结构进行筛选:&/p&&div class=&highlight&&&pre&&code class=&language-text&&filter(lambda x: x % 2, [1, 2, 3, 4, 5])
# 筛选奇数,[1, 3, 5]
&/code&&/pre&&/div&&p&需要注意的是,对于filter和map,在Python2中返回结果是列表,Python3中是生成器。&/p&&h2&&b&5.2.6 列表生成(list comprehension)&/b&&/h2&&p&列表生成是Python2.0中加入的一种语法,可以非常方便地用来生成列表和迭代器,比如上节中map的两个例子和filter的一个例子可以用列表生成重写为:&/p&&div class=&highlight&&&pre&&code class=&language-text&&[x**2 for x in [1, 2, 3, 4]]
# [1, 4, 9 16]
[sum(x) for x in zip([1, 2, 3], [5, 6, 7])] # [6, 8, 10]
[x for x in [1, 2, 3, 4, 5] if x % 2]
# [1, 3, 5]
&/code&&/pre&&/div&&p&zip()函数可以把多个列表关联起来,这个例子中,通过zip()可以按顺序同时输出两个列表对应位置的元素对。有一点需要注意的是,zip()不会自动帮助判断两个列表是否长度一样,所以最终的结果会以短的列表为准,想要以长的列表为准的话可以考虑itertools模块中的izip_longest()。如果要生成迭代器只需要把方括号换成括号,生成字典也非常容易:&/p&&div class=&highlight&&&pre&&code class=&language-text&&iter_odd = (x for x in [1, 2, 3, 4, 5] if x % 2)
print(type(iter_odd))
# &type 'generator'&
square_dict = {x: x**2 for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
&/code&&/pre&&/div&&p&至于列表生成和map/filter应该优先用哪种,这个问题很难回答,不过Python创始人Guido似乎不喜欢map/filter/reduce,他曾在表示过一些从函数式编程里拿来的特性是个错误。&/p&&h2&&b&5.2.7 字符串&/b&&/h2&&p&Python中字符串相关的处理都非常方便,来看例子:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = 'Life is short, you need Python'
# 'life is short, you need Python'
# 'LIFE IS SHORT, YOU NEED PYTHON'
a.count('i')
a.find('e')
# 从左向右查找'e',3
a.rfind('need')
# 从右向左查找'need',19
a.replace('you', 'I')
# 'Life is short, I need Python'
tokens = a.split()
# ['Life', 'is', 'short,', 'you', 'need', 'Python']
b = ' '.join(tokens) # 用指定分隔符按顺序把字符串列表组合成新字符串
c = a + '\n'
# 加了换行符,注意+用法是字符串作为序列的用法
c.rstrip()
# 右侧去除换行符
[x for x in a]
# 遍历每个字符并生成由所有字符按顺序构成的列表
'Python' in a
&/code&&/pre&&/div&&p&Python2.6中引入了format进行字符串格式化,相比在字符串中用%的类似C的方式,更加强大方便:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = 'I’m like a {} chasing {}.'
# 按顺序格式化字符串,'I’m like a dog chasing cars.'
a.format('dog', 'cars')
# 在大括号中指定参数所在位置
b = 'I prefer {1} {0} to {2} {0}'
b.format('food', 'Chinese', 'American')
# &代表右对齐,&前是要填充的字符,依次输出:
for i in [1, 19, 256]:
print('The index is {:0&6d}'.format(i))
# &代表左对齐,依次输出:
# *---------
# ****------
# *******---
for x in ['*', '****', '*******']:
progress_bar = '{:-&10}'.format(x)
print(progress_bar)
for x in [0., 3e-18]:
print('{:.6f}'.format(x))
# 按照小数点后6位的浮点数格式
print('{:.1e}'.format(x))
# 按照小数点后1位的科学记数法格式
print ('{:g}'.format(x))
# 系统自动选择最合适的格式
template = '{name} is {age} years old.'
c = template.format(name='Tom', age=8)) # Tom is 8 years old.
d = template.format(age=7, name='Jerry')# Jerry is 7 years old.
&/code&&/pre&&/div&&p&format在生成字符串和文档的时候非常有用,更多更详细的用法可以参考Python官网:&/p&&p&&a href=&//link.zhihu.com/?target=https%3A//docs.python.org/2/library/string.html%23format-specification-mini-language& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&7.1. string – Common string operations – Python 2.7.13 documentation&/a&&/p&&h2&&b&5.2.8 文件操作和pickle&/b&&/h2&&p&在Python中,推荐用上下文管理器(with-as)来打开文件,IO资源的管理更加安全,而且不用老惦记着给文件执行close()函数。还是举例子来说明,考虑有个文件name_age.txt,里面存储着名字和年龄的关系,格式如下:&/p&&div class=&highlight&&&pre&&code class=&language-text&&Tom,8
&/code&&/pre&&/div&&p&读取文件内容并全部显示:&/p&&div class=&highlight&&&pre&&code class=&language-text&&with open('name_age.txt', 'r') as f: # 打开文件,读取模式
lines = f.readlines()
# 一次读取所有行
for linein lines:
# 按行格式化并显示信息
name, age = line.rstrip().split(',')
print('{} is {} years old.'.format(name, age))
&/code&&/pre&&/div&&p&open()的第一个参数是文件名,第二个参数是模式。文件的模式一般有四种,读取(r),写入(w),追加(a)和读写(r+)。如果希望按照二进制数据读取,则将文件模式和b一起使用(wb, r+b…)。&/p&&p&再考虑一个场景,要读取文件内容,并把年龄和名字的顺序交换存成新文件age_name.txt,这时可以同时打开两个文件:&/p&&div class=&highlight&&&pre&&code class=&language-text&&with open('name_age.txt', 'r') as fread, open('age_name.txt', 'w') as fwrite:
line = fread.readline()
while line:
name, age = line.rstrip().split(',')
fwrite.write('{},{}\n'.format(age, name))
line = fread.readline()
&/code&&/pre&&/div&&p&有的时候我们进行文件操作是希望把对象进行序列化,那么可以考虑用pickle模块:&/p&&div class=&highlight&&&pre&&code class=&language-text&&import pickle
&I'm like a dog chasing cars.&,
&I wouldn't know what to do if I caught one...&,
&I'd just do things.&
with open('lines.pkl', 'wb') as f: # 序列化并保存成文件
pickle.dump(lines, f)
with open('lines.pkl', 'rb') as f: # 从文件读取并反序列化
lines_back = pickle.load(f)
print(lines_back)
# 和lines一样
&/code&&/pre&&/div&&p&注意到,序列化的时候就得使用b模式了。Python2中有个效率更高的pickle叫cPickle,用法和pickle一样,在Python3中就只有一个pickle。&/p&&h2&&b&5.2.9 异常&/b&&/h2&&p&相比起其他一些语言,在Python中我们可以更大胆地使用异常,因为异常在Python中是非常常见的存在,比如下面这种简单的遍历:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = ['Why', 'so', 'serious', '?']
for x in a:
&/code&&/pre&&/div&&p&当用for进行遍历时,会对要遍历的对象调用iter()。这需要给对象创建一个迭代器用来依次返回对象中的内容。为了能成功调用iter(),该对象要么得支持迭代协议(定义__iter__()),要么得支持序列协议(定义__getitem__())。当遍历结束时,__iter__()或者__getitem__()都需要抛出一个异常。__iter__()会抛出StopIteration,而__getitem__()会抛出IndexError,于是遍历就会停止。&/p&&p&在深度学习中,尤其是数据准备阶段,常常遇到IO操作。这时候遇到异常的可能性很高,采用异常处理可以保证数据处理的过程不被中断,并对有异常的情况进行记录或其他动作:&/p&&div class=&highlight&&&pre&&code class=&language-text&&for filepathin filelist:
# filelist中是文件路径的列表
with open(filepath, 'r') as f:
# 执行数据处理的相关工作
print('{} is processed!'.format(filepath))
except IOError:
print('{} with IOError!'.format(filepath))
# 异常的相应处理
&/code&&/pre&&/div&&h2&&b&5.2.10 多进程(multiprocessing)&/b&&/h2&&p&深度学习中对数据高效处理常常会需要并行,这时多进程就派上了用场。考虑这样一个场景,在数据准备阶段,有很多文件需要运行一定的预处理,正好有台多核服务器,我们希望把这些文件分成32份,并行处理:&/p&&div class=&highlight&&&pre&&code class=&language-text&&from multiprocessing import Process#, freeze_support
def process_data(filelist):
for filepathin filelist:
print('Processing {} ...'.format(filepath))
# 处理数据
if __name__ == '__main__':
# 如果是在Windows下,还需要加上freeze_support()
#freeze_support()
# full_list包含了要处理的全部文件列表
n_total = len(full_list) # 一个远大于32的数
n_processes = 32
# 每段子列表的平均长度
length = float(n_total) / float(n_processes)
# 计算下标,尽可能均匀地划分输入文件列表
indices = [int(round(i*length)) for i in range(n_processes+1)]
# 生成每个进程要处理的子文件列表
sublists = [full_list[indices[i]:indices[i+1]] for i in range(n_processes)]
# 生成进程
processes = [Process(target=process_data, args=(x,)) for x in sublists]
# 并行处理
for p in processes:
for p in processes:
&/code&&/pre&&/div&&p&其中 &b&if&/b& __name__ &b&==&/b& ‘__main__’用来标明在import时不包含,但是作为文件执行时运行的语句块。为什么不用多线程呢?简单说就是Python中线程的并发无法有效利用多核,如果有兴趣的读者可以从下面这个链接看起:&/p&&p&&a href=&//link.zhihu.com/?target=https%3A//wiki.python.org/moin/GlobalInterpreterLock& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&GlobalInterpreterLock – Python Wiki&/a&&/p&&h2&&b&5.2.11 os模块&/b&&/h2&&p&深度学习中的数据多是文件,所以数据处理阶段和文件相关的操作就非常重要。除了文件IO,Python中一些操作系统的相关功能也能够非常方便地帮助数据处理。想象一下我们有一个文件夹叫做data,下边有3个子文件夹叫做cat,dog和bat,里面分别是猫,狗和蝙蝠的照片。为了训练一个三分类模型,我们先要生成一个文件,里面每一行是文件的路径和对应的标签。定义cat是0,dog是1,bat是2,则可以通过如下脚本:&/p&&div class=&highlight&&&pre&&code class=&language-text&&import os
# 定义文件夹名称和标签的对应关系
label_map = {
with open('data.txt', 'w') as f:
# 遍历所有文件,root为当前文件夹,dirs是所有子文件夹名,files是所有文件名
for root, dirs, filesin os.walk('data'):
for filenamein files:
filepath = os.sep.join([root, filename])
# 获得文件完整路径
dirname = root.split(os.sep)[-1]
# 获取当前文件夹名称
label = label_map[dirname]
# 得到标签
line = '{},{}\n'.format(filepath, label)
f.write(line)
&/code&&/pre&&/div&&p&其中,os.sep是当前操作系统的路径分隔符,在Unix/Linux中是’/’,Windows中是’\\’。有的时候我们已经有了所有的文件在一个文件夹data下,希望获取所有文件的名称,则可以用os.listdir():&/p&&div class=&highlight&&&pre&&code class=&language-text&&filenames = os.listdir('data')
&/code&&/pre&&/div&&p&os也提供了诸如拷贝,移动和修改文件名等操作。同时因为大部分深度学习框架最常见的都是在Unix/Linux下使用,并且Unix/Linux的shell已经非常强大(比Windows好用太多),所以只需要用字符串格式化等方式生成shell命令的字符串,然后通过os.system()就能方便实现很多功能,有时比os,还有Python中另一个操作系统相关模块shutil还要方便:&/p&&div class=&highlight&&&pre&&code class=&language-text&&import os, shutil
filepath0 = 'data/bat/IMG_000001.jpg'
filepath1 = 'data/bat/IMG_000000.jpg'
# 修改文件名
os.system('mv {} {}'.format(filepath0, filepath1))
#os.rename(filepath0, filepath1)
# 创建文件夹
dirname = 'data_samples'
os.system('mkdir -p {}'.format(dirname))
#if not os.path.exists(dirname):
os.mkdir(dirname)
# 拷贝文件
os.system('cp {} {}'.format(filepath1, dirname))
#shutil.copy(filepath1, dirname)
&/code&&/pre&&/div&&hr&&p&你想更深入了解学习Python知识体系,你可以看一下我们花费了一个多月整理了上百小时的几百个知识点体系内容: &/p&&p&&a href=&//link.zhihu.com/?target=http%3A//www.magedu.com/73198.html%3FPython_wenda_zhihu_jinke_pythonrumenxuexizhinan_question/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【超全整理】《Python自动化全能开发从入门到精通》笔记全放送&/a&&/p&
Life is short, you need Python人生苦短,我用Python— Bruce Eckel5.1 Python简介本章将介绍Python的最基本语法,以及一些和深度学习还有计算机视觉最相关的基本使用。5.1.1 Python简史Python是一门解释型的高级编程语言,特点是简单明确。Python作者是荷…
&figure&&img src=&https://pic1.zhimg.com/v2-7b6c5ee70a2ec_b.jpg& data-rawwidth=&1680& data-rawheight=&1050& class=&origin_image zh-lightbox-thumb& width=&1680& data-original=&https://pic1.zhimg.com/v2-7b6c5ee70a2ec_r.jpg&&&/figure&&p&不同于目前互联网上经常见到的图形学书单推荐,本文侧重收集、整理图形学各个方向研究所需要的各个方面(基础知识,领域重要著作,工具链参考手册),&b&以供想了解/快速上手该细分领域的同学参考。&/b&&br&&/p&&p&&b&本书单长期更新,请在评论区中留下您的反馈意见/补充推荐,我们会定期对这个书单做更新,并在贡献者位置附上您的ID。&/b&&/p&&p&目前细分方向暂时分为Introduction(介绍图形学、电影/动画工业的基础知识),Geometry Processing(几何处理,建模等),Rendering(离线/实时渲染),Animation and Simulation(动画/物理模拟),Mathematics(图形学研究需要用到的数学知识),Toolchain(图形学研究常用工具链)。如果您对这些方向分类有新的想法,我们欢迎您的反馈。&/p&&p&由于编者水平有限,本文难免有遗漏和不妥之处,请不吝赐教。&/p&&p&Contributors:&/p&&p&&a href=&https://www.zhihu.com/people/6f48dcc0b964ade9d07f& data-hash=&6f48dcc0b964ade9d07f& class=&member_mention& data-editable=&true& data-title=&@硕鼠酱& data-hovercard=&p$b$6f48dcc0b964ade9d07f&&@硕鼠酱&/a& ,&a href=&https://www.zhihu.com/people/9f3ee58deeb11e4503d7& data-hash=&9f3ee58deeb11e4503d7& class=&member_mention& data-editable=&true& data-title=&@李旻辰& data-hovercard=&p$b$9f3ee58deeb11e4503d7&&@李旻辰&/a& ,&a href=&https://www.zhihu.com/people/ecf74d1b95762c56eebfe& data-hash=&ecf74d1b95762c56eebfe& class=&member_mention& data-editable=&true& data-title=&@Raymond& data-hovercard=&p$b$ecf74d1b95762c56eebfe&&@Raymond&/a&,&a href=&https://www.zhihu.com/people/0e3acf861eb158b023eee& data-hash=&0e3acf861eb158b023eee& class=&member_mention& data-hovercard=&p$b$0e3acf861eb158b023eee& data-editable=&true& data-title=&@丁欧南&&@丁欧南&/a&,&a href=&https://www.zhihu.com/people/a33efee5e117cdf& data-hash=&a33efee5e117cdf& class=&member_mention& data-title=&@FAQ& data-hovercard=&p$b$a33efee5e117cdf& data-editable=&true&&@FAQ&/a&,&a href=&https://www.zhihu.com/people/570a76c34d68ba0ff9c69cd4c79ecf56& data-hash=&570a76c34d68ba0ff9c69cd4c79ecf56& class=&member_mention& data-editable=&true& data-title=&@CodingHare& data-hovercard=&p$b$570a76c34d68ba0ff9c69cd4c79ecf56&&@CodingHare&/a&&/p&&br&&br&&h2&Introduction&/h2&&blockquote&Interactive computer graphics : a top-down approach with shader-based OpenGL / Edward Angel et al.&/blockquote&相当不错的图形学入门读物,偏重实时渲染。用OpenGL(新版本为WebGL)作为教学,简单容易上手。&blockquote&The Art of 3D Computer Animation and Effects by Isaac V. Kerlow&/blockquote&&p&全面介绍电影/动画工业的方方面面,由迪斯尼工作人员攒书,值得一看。&/p&&br&&h2&Geometry Processing&/h2&&blockquote&&p&Computational Geometry: Algorithms and Applications. Third Edition. Mark de Berg, et al&/p&&/blockquote&&p&计算几何经典之作,深入浅出,例子很多,每一章开头都有本章内容的实际应用,书后附有大量习题。&/p&&blockquote&Polygon mesh processing. CRC press. Botsch et al. 2010&/blockquote&&p&包括基本的几何形体处理算法的讲解,比如平滑降噪、参数化、三角剖分、简化与近似、形变等。&/p&&blockquote&Discrete Differential Geometry: An Applied Introduction. Keenan Crane 2015&/blockquote&&p&讲述传统微分几何的基本概念如何在离散计算中得到应用,同时也会涉及到对一些相关数学工具的应用的探讨。内容主要包括曲率、平行转移、外蕴代数和微积分、拓扑、霍奇分解、保角映射、有限元方法等。&br&&/p&&blockquote&Vector Field Processing on Triangle Meshes. Fernando de Goes et al. 2015&/blockquote&&p&讲述如何在几何体表面的切空间定义向量场并应用到对几何形体的处理中。本文也着重讲解了如何将传统微分几何的概念离散化到三角形网格上,选取三角形、顶点、边作为离散元分别有何优缺点。&/p&&br&&h2&Rendering&/h2&&blockquote&Physically Based Rendering, From Theory to Implementation /Matt Pharr&/blockquote&&p&讲解详细体系完备,更难能可贵的是本书配套一个渲染系统,书后习题提供了参考文献和思路来改进这个渲染系统,学练结合,夫复何求?&/p&&blockquote&Real-Time Rendering, Tomas Akenine-Moller, Eric Haines & Naty Hoffman&/blockquote&&p&与离线渲染相对应的实时渲染经典著作,针对现代图形渲染管线、GPU、着色器等有详细讲解。同时总结了大量游戏开发中非常实用的算法。&/p&&br&&h2&Animation and Simulation&/h2&&blockquote& Fluid simulation for computer graphics / Robert Bridson&/blockquote&&p&作者流体模拟届大牛Bridson,从NS方程的推导入手,详细介绍流体模拟的经典算法,是做物理模拟方向的同学几乎人手一本的参考书。&/p&&blockquote&Nonlinear Continuum Mechanics for Finite Element Analysis / Javier Bonet & Richard D. Wood&/blockquote&&p&固体、软体模拟、声音合成等方向的必读物。从最简单的线性机械学介绍到非线性机械学,对各种应力模型都有详细的介绍。同时对不同机械学模型的有限元分析也进行了深入的讲解。&/p&&blockquote&&p&Boundary Element Method / Stefan A. Sauter & Christoph Schwab&/p&&/blockquote&&p&本书详细介绍了边界元方法的理论和具体的数值方法。从边界元的概念、伽辽金方法等,讲述到椭圆边界积分方程的性质和解法,之后详细介绍了边界元方法及其在不同应用下的各种变通方法,最后也介绍了一些相关的线性方程求解和误差分析方法。&/p&&blockquote&Rigid Body Simulation I & II / David Baraff&/blockquote&&p&刚体模拟的入门读物,从最基本的刚体运动方程讲到刚体碰撞等。作者是皮克斯动画工作室的高级研究员,其开发的布料模拟算法已被广泛采纳于各种游戏和特效引擎中。&/p&&p&&a href=&https://www.zhihu.com/people/a33efee5e117cdf& data-hash=&a33efee5e117cdf& class=&member_mention& data-hovercard=&p$b$a33efee5e117cdf& data-editable=&true& data-title=&@FAQ&&@FAQ&/a&推荐&/p&&blockquote&The Arts of Fluid Animation / Jos Stam CRC Press&/blockquote&&p&Jos Stam 的 The Arts of Fluid Animation 讲得很有趣,可以作为引起兴趣的一本入门书籍,还带他的经典代码。&/p&&blockquote&&p&&a href=&https://link.zhihu.com/?target=https%3A//software.intel.com/en-us/articles/fluid-simulation-for-video-games-part-1/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Fluid Simulation for Video Games &/a& &/p&&/blockquote&&p&今天在办公室整理资料的时候发现当时一开始学习流体的时候看得很起劲的一个系列教程,叫Fluid Simulation for Video Games (因为我以前是做Game dev的,但后来兴趣有所改变…),这个系列提供很多关于流体的信息,但都不是那种看了作呕的教科书,它还提供一些源码可以玩。&/p&&p&&a href=&https://www.zhihu.com/people/570a76c34d68ba0ff9c69cd4c79ecf56& data-hash=&570a76c34d68ba0ff9c69cd4c79ecf56& class=&member_mention& data-editable=&true& data-title=&@CodingHare& data-hovercard=&p$b$570a76c34d68ba0ff9c69cd4c79ecf56&&@CodingHare&/a&推荐&/p&&blockquote&Kim, Doyub. &i&Fluid Engine Development&/i&. CRC Press, 2017.&/blockquote&推荐一本 Doyub Kim 的 FLUID ENGINE DEVELOPMENT, ISBN978-1-,基本上是手把手的从零开始教你写流体解算器啦,对像我一样的自学新手很有帮助&br&&h2&Mathematics&/h2&&blockquote&Linear Algebra and Its Applications / Peter Lax&/blockquote&&p&作者是科学计算领域大家,这本书前面从分析的视角讲代数,后文从代数扩展到计算数学,是用一本书快速温习多个领域的不二之选&b&。本书观点较高,适合有本科数学基础的同学参考。&/b&&/p&&blockquote&&p&Numerical
Solution of
Time-Dependent Advection-Diffusion-Reaction
Equations / Willem Hundsdorfer and Jan Verwer&/p&&/blockquote&&p&从Method of Lines讲解抛物方程数值求解的一本观点新颖的著作,可供做流体模拟/CFD的同学参考。&/p&&a href=&https://link.zhihu.com/?target=http%3A//arminstraub.com/math/what-is-column& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&What is...&/a&&p&AMS邀请各位大神编写的给数学爱好者阅读的科普小短文系列,能找到很多很有趣的东西 :)
&/p&&blockquote& Numerical Mathematics and Computing / Cheney, E., and David Kincaid.&/blockquote&&p&一本比较新的计算数学著作,详细介绍了科学计算各个方面,知识比较新,并有详细的例子。&/p&&blockquote&Modern Mathematics and Applications in Computer Graphics and Vision / Hongyu Guo&/blockquote&&p&这本书收集了很多计算机图形学和视觉科学需要用到的现代数学知识。&/p&&blockquote&Numerical Optimization / Jorge Nocedal & Stephen J. Wright&/blockquote&&p&数值优化的经典著作,作者是开发了著名非线性优化算法L-BFGS的大牛,和数值计算相关领域的必读书目。&/p&&blockquote&Partial Differential Equations / L. C. Evans&/blockquote&&p&本书从应用角度全面地介绍了偏微分方程的相关内容,结合经典的工科应用,详细讲述了偏微分方程的类型、求解方法以及相关理论,适合已有数学分析基础的同学学习。&/p&&blockquote&微积分学教程(三卷本) / 菲赫今哥尔茨&/blockquote&&p&这套书是享誉世界的著作。然而由于体量实在太大,所以更适合作为参考资料使用。这套书讲解相当详细,每一章几乎都可以自成体系,并且配备数量可观的例题,是快速回忆微积分相关公式/定理绝佳的参考资料。&/p&&blockquote&Ascher, Uri M., and Linda R. Petzold. &i&Computer methods for ordinary differential equations and differential-algebraic equations&/i&. Vol. 61. Siam, 1998.&/blockquote&&p&ODE数值解法方面的著作,配有习题和很多具体例子,也照顾到了对数学原理的讲解。这本书美中不足之处是省略了很多证明的细节。&/p&&p&&a href=&https://www.zhihu.com/people/0e3acf861eb158b023eee& data-hash=&0e3acf861eb158b023eee& class=&member_mention& data-editable=&true& data-title=&@丁欧南& data-hovercard=&p$b$0e3acf861eb158b023eee&&@

我要回帖

更多关于 海美迪机顶盒哪一款 的文章

 

随机推荐