python学习番外篇之print输出函数用法及原理总结

本文总结了Python3中print函数的用法和原理,包括直接输出、格式化输出,以及如何避免自动换行。还探讨了print函数的内部方法sep和end,以及它与Python2中print语句的区别,强调了灵活性和组件化的优点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

print输出函数用法及原理总结:

        在python2.x中,print作为关键字使用,输出用print语句输出,例如,x=5 ; print x ,但在python3.x中,print则成为了一个函数,输出用print()函数输出,例如:x=5 ; print(x)(python2.x中,print作为作为关键字用语句输出,可以加或不加小括号,但python3.x中作为函数必须加小括号。)

一:print函数的用法总结

1:直接输出

        无论是在python2.x中还是在python3.x中,对于字符串,数值,布尔,列表,字典等,print都是直接输出

                -print(变量/字符串)

2:格式化输出

        print()支持参数格式化输出,与C语言中用法类似、

    字符串格式化转换类型

        转换类型          含义

        d                   带符号的十进制整数

        o                   不带符号的八进制

        u                   不带符号的十进制

        x或X              不带符号的十六进制

        e 或E             科学计数法表示的浮点数

        f,F                 十进制浮点数

        C                  单字符(接受整数或者单字符字符串)

        r                    字符串(使用repr转换任意python对象)

        s                   字符串(使用str转换任意python对象)

  1. >>> pi =  3.141592653  
  2. >>>  print( '%10.3f' % pi)  #字段宽10,精度3  
  3.       3.142  
  4. >>>  print( "pi = %.*f" % ( 3,pi))  #用*从后面的元组中读取字段宽度或精度  
  5. pi =  3.142  
  6. >>>  print( '%010.3f' pi)  #用0填充空白  
  7. 000003.142  
  8. >>>  print( '%-10.3f' % pi)  #左对齐  
  9. 3.142       
  10. >>>  print( '%+f' % pi)  #显示正负号  
  11. + 3.141593  

《Python基础编程》中对格式化输出的总结:

(1). %字符:标记转换说明符的开始

(2). 转换标志:-表示左对齐;+表示在转换值之前要加上正负号;“”(空白字符)表示正数之前保留空格;0表示转换值若位数不够则用0填充

(3). 最小字段宽度:转换后的字符串至少应该具有该值指定的宽度。如果是*,则宽度会从值元组中读出。

(4). 点(.)后跟精度值:如果转换的是实数,精度值就表示出现在小数点后的位数。如果转换的是字符串,那么该数字就表示最大字段宽度。如果是*,那么精度将从元组中读出


3:print()不想自动换行的解决办法

        在python2.x中,在输出内容的结尾处加上逗号  例如:print ('123',)

        在python3.x中,在输出内容的结尾处加上end=' '  例如:print ('123',end='')


二:print函数原理总结:

1:print函数的内置方法sep与end

        set是单词separation的简称,即代表分隔符,默认是空格

        end代表结束出的符号,默认是一个换行符

        print函数输出多个用‘,’隔开的字符串时,输出的语句中,用空格代替,结尾用换行代替

                >>> print ('hello','world')

                hello world

2:print函数与print语句

转自:https://blog.youkuaiyun.com/m0_37531667/article/details/74963449

print语句

在Python 2中,print语句最简单的使用形式就是print A,这相当于执行了sys.stdout.write(str(A) + '\n')。如果你以逗号为分隔符,传递额外的参数(argument),这些参数会被传递至str()函数,最终打印时每个参数之间会空一格。例如,print A, B, C相当于sys.stdout.write(' '.join(map(str, [A, B, C])) + '\n')。如果print语句的最后再加上一个逗号,那么就不会再添加断行符(\n),也就是说:print A相当于sys.stdout.write(str(A))

从 2.0版本开始,Python引入了print >>的语法,作用是重定向print语句最终输出字符串的文件。例如,print >> output, A相当于output.write(str(A) + '\n')

print函数

如果用Python来实现print函数,它的函数定义应该是这样的:

import sys

def print(*objects, sep=None, end=None, file=None, flush=False):
    """A Python translation of the C code for builtins.print().


"""
    if sep is None:
        sep = ' '
    if end is None:
        end = '\n'
    if file is None:
        file = sys.stdout
    file.write(sep.join(map(str, objects)) + end)
    if flush:
        file.flush()

从上面的代码中,我们可以发现:Python 3中的print函数实现了print语句的所有特性。

print A == print(A)
print A, B, C == print(A, B, C)
print A, == print(A, end='')
print >> output, A == print(A, file=output)

从上面的示例代码中我们就可以看出,使用print函数有明显的好处:与使用print语句相比,我们现在能够指定其他的分隔符(separator)和结束符(end string)。

关键在于灵活性

将print变成函数的真正巧妙之处在与灵活性,但这点并不容易被人发觉。print成为函数之后,给Python用户和Python开发团队带来了很大的灵活性。对于用户来说,这可以让你把print当作表达式(expression)使用;相比之下,print语句就只能作为语句使用。举个例子,假设你想在每一行后面打印一个省略号(ellipsis),表示这行尚未结束。使用print语句的话,你有两种选择:

# 手动实现 ...
print A, '...'

# 可复用的实现(这种方式也适用于print函数) ...
def ellipsis_print(*args):
    for arg in args:
        print arg, '',
    print '...'

但是在Python 3中,你可以选择更好的解决方式:

# 手动实现 ...
print(A, end='...\n')

# 多个可复用的解决方案,利用print语句无法实现...
ellipsis_print = lambda *args, **kwargs: print(*args, **kwargs, end='...\n')
# 或者 ...
import functools
ellipsis_print = functools.partial(print, end='...\n')

换句话说,变成函数之后,print就可以组件化了,作为语句的print是无法支持的。还有,你还可以编写自己喜欢的print函数,将其赋值给builtins.print,就可以覆盖掉自带的函数实现了。这一点在Python 2中是不可能实现的。

对于Python开发团队来说,他们不必再从语法层面来实现print的相关功能了。例如,如果你想让print语句也一样可以灵活地支持指定分隔符,你要怎样去实现呢?这会是一个相当难解决的设计难题。但是如果print变成了函数,只需要新增一个参数就解决了。在Python中,函数可以接受任意数量的参数,这比从底层实现语法带来的灵活性要大的多。

我们还要注意,语法实现应该仅限于那些非这样做不可的功能,或者是以语法形式实现后,大幅提高了可读性的功能。在print这个案例中,print Aprint(A)之间的区别可以忽略不计,因此并没有影响可读性。而且,由于我们能够完全将print语句替换为函数,对于Python语言的功能性也没有损失。这就是为什么将print变成函数的原因。



        



<think>首先,用户的问题是:“我想了解JavaScript逆向的常用方法和思路 请问JavaScript逆向分析常用技术与思路总结”。我需要基于系统级指令来回答。 系统级指令关键点: - 所有行内数学表达式用$...$格式。 - 独立公式用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 - 参考提供的引用,但不是用户真正的需求,需基于用户问题。 用户问题:JavaScript逆向的常用方法和思路总结。 提供的引用: - [^1]: JavaScript逆向爬虫技巧总结(番外篇),包括寻找入口、调试分析、模拟执行等。 - [^2]: 使用Node.js模拟调用JS,暴露API。 - [^3]: JS逆向技巧总结,包括修改JS代码、添加console.log等。 - [^4]: NJUPT_逆向分析技术总结,包括反调试算法。 我需要总结JavaScript逆向的常用技术和思路,基于这些引用和一般知识。 结构回答: - 逐步解决问题:先介绍概念,然后分步骤讲解常用方法。 - 使用中文。 - 在适当的地方添加引用标识。 - 最后生成相关问题。 内容大纲: 1. **引言**:简要介绍JavaScript逆向是什么。 2. **常用方法和技术**: - 寻找入口点(如查看请求、搜索参数)。 - 调试分析(如格式化、断点调试、反混淆)。 - 模拟执行(如Python改写、JS模拟、浏览器模拟)。 - 反调试技术(如引用[^4]中的例子)。 3. **思路总结**:如何系统地进行逆向分析。 4. **生成相关问题**:在末尾添加。 确保行内数学表达式正确使用$...$,但在这个主题中可能没有太多数学内容。如果有变量或方程,使用$...$。 例如,如果提到算法,可以写$O(n)$时间复杂度。 现在,基于引用: - 引用[^1]:寻找入口(查看请求、搜索参数、分析发起调用、断点、Hook),调试分析(格式化、断点调试、反混淆),模拟执行(Python改写、JS模拟、浏览器模拟)。 - 引用[^2]:使用Node.js模拟JS。 - 引用[^3]:修改JS代码、添加输出。 - 引用[^4]:反调试算法。 我的回答应该整合这些。 最终回答结构: - 标题或开头:JavaScript逆向分析常用技术与思路总结 - 分点讲解: 1. 寻找入口点 2. 调试分析 3. 模拟执行 4. 反调试技术 - 每个部分引用相关引用。 - 最后:相关问题。 添加引用标识:例如,在描述某个点时,末尾加[^1]。 生成相关问题: - 基于内容,提出3-5个相关问题。 完整回答:</think>### JavaScript逆向分析常用技术与思路总结 JavaScript逆向分析是指通过技术手段,解析和理解JavaScript代码的执行逻辑,常用于爬虫开发、安全审计或调试等场景。其核心目标是定位关键逻辑(如加密算法、参数生成)并进行模拟或修改。以下是基于常用方法和思路的逐步总结,确保结构清晰且真实可靠。参考了相关文献,我会在描述中自然地添加引用标识。 #### 1. **寻找入口点** JavaScript逆向的第一步是定位关键代码的起始位置。常见方法包括: - **查看网络请求**:使用浏览器开发者工具(如Chrome DevTools)分析XHR/Fetch请求,观察请求参数(如加密token或签名)的来源[^1]。 - **搜索参数**:在JS代码中全局搜索特定参数名(如`token`或`sign`),快速定位相关函数。例如,搜索`$key$`变量可能指向加密逻辑。 - **分析发起调用**:追踪事件监听器(如点击事件)或定时器,找到JS函数的调用栈。例如,通过`addEventListener`定位用户交互触发的代码[^1]。 - **Hook技术**:注入Hook脚本拦截关键函数(如`window.crypto`),实时输出参数和返回值,便于分析[^1]。例如,Hook `XMLHttpRequest.open` 来捕获请求数据。 - **断点调试**:在关键函数设置断点(如`debugger`语句),逐步执行代码并观察变量变化[^1][^3]。 思路总结:从网络请求或用户行为入手,逐步缩小范围,避免盲目分析。优先关注高频调用的函数,如加密或数据提交模块[^1]。 #### 2. **调试分析** 定位代码后,需深入调试以理解逻辑。核心方法包括: - **代码格式化**:使用工具(如Chrome的Pretty Print)将混淆代码转为可读格式,便于识别变量名和结构[^1]。 - **断点调试**:在开发者工具中设置条件断点,监视变量值(如`$localVar$`)。例如,分析循环中的计数器变化[^1][^3]。 - **反混淆**:处理混淆代码(如变量名简化为`a,b,c`),使用AST解析器(如Babel)还原逻辑。例如,将`eval`函数替换为可读代码[^1]。 - **动态修改**:在调试中实时添加`console.log`输出变量值,或删除干扰代码(如反调试陷阱)[^3]。例如,插入`console.log($value$)` 观察中间结果。 思路总结:结合静态分析(阅读代码)和动态调试(运行时观察),优先处理简单逻辑再攻克复杂部分。注意保存修改后的JS文件,便于后续模拟[^3]。 #### 3. **模拟执行** 理解逻辑后,需在本地复现JS行为。常用方法包括: - **Python改写**:用Python重写JS算法(如加密函数),适用于简单逻辑。例如,将JS的`CryptoJS.MD5`转为Python的`hashlib.md5`[^1]。 - **JS模拟执行**:通过Node.js运行JS代码,并暴露为API(如Express框架),实现跨语言调用。例如,将加密函数封装为REST接口[^2]。 - **浏览器模拟**:使用无头浏览器(如Puppeteer或Selenium)完整加载页面,自动执行JS并提取数据。适用于动态渲染的网站[^1][^3]。 思路总结:优先选择轻量级方案(Python或Node.js),复杂场景用浏览器模拟。测试时需验证输出一致性,如比较模拟结果与真实请求[^2]。 #### 4. **反调试技术** 逆向中常遇反调试保护,需针对性应对: - **反调试算法**:如引用[^4]中的代码,通过异常处理检测调试器(如`__try`块修改标志位)。核心原理是利用调试器行为差异(如断点触发异常),实现效果是阻止调试或返回假数据。 - **应对方法**:禁用浏览器开发者工具、Hook反调试函数(如覆盖`console.debug`),或使用反反调试工具(如Tampermonkey脚本)[^4][^3]。 思路总结:反调试是常见障碍,需结合调试和Hook技术绕过。重点分析异常处理或定时检测逻辑[^4]。 ### 相关问题 1. 如何Hook JavaScript函数来捕获加密参数? 2. 使用Node.js模拟JS执行时,如何处理浏览器环境依赖? 3. JavaScript反混淆有哪些自动化工具? 4. 在逆向分析中,如何识别和绕过常见的反调试机制? 5. 浏览器模拟执行(如Puppeteer)的性能优化方法有哪些? [^1]: JavaScript 逆向爬虫技巧总结(番外篇),包括寻找入口、调试分析和模拟执行方法。 [^2]: 使用 Node.js 和 Express 模拟 JS 调用,暴露为 API 实现跨语言支持。 [^3]: JS逆向技巧总结,涉及动态修改代码和调试优化。 [^4]: NJUPT_逆向分析技术总结,描述反调试算法原理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值