【python 面试总结】

1. python的特征有哪些?考定义、考区别、考细节

解释型语言、面向对象、动态语言不需要声明变量的类型

2. 你知不知道什么是PEP?

PEP代表Python Enhancement Proposal。
目的是为Python社区提供一个讨论和达成共识的平台,以决定Python语言未来的发展和变化。
一旦一个PEP被广泛接受并最终确定,它就会成为Python语言规范的一部分。
Python社区鼓励所有感兴趣的开发者参与到PEP的讨论和决策过程中来,以共同推动Python语言的发展。通过这种方式,Python社区能够确保Python语言的发展方向符合最广泛用户的需求和期望。

3. python怎么管理内存?

核心API提供了一系列函数,允许程序员更精细地控制内存的使用。例如,可以使用malloc和free等函数手动分配和释放内存。
此外,Python提供了一些数据结构,如列表和字典,它们会自动管理内存使用,随着数据的添加和删除动态地调整大小。
为了确保内存使用效率和避免内存泄漏,Python的内存管理器还负责跟踪不再使用的对象,并在适当的时候释放它们所占用的内存。这是通过垃圾回收器完成的,它定期搜索并回收不再可达的对象。

4. 什么是PYTHONPATH?

当你在代码中使用 import 语句引入模块时,Python 解释器不仅会在当前目录下查找该模块,还会在 PYTHONPATH 所列出的目录中进行查找。这使得用户可以将自定义模块或第三方库放在特定的目录中,而无需将这些目录添加到代码中的 sys.path 列表里。

5. 什么是python模块?Python中有哪些常用的内置模块?

Python模块是包含Python代码的.py文件。此代码可以是函数类或变量。一些常用的内置模块包括:sys、math、random、data time、JSON。

6. Python数组和列表有什么区别?列表和元组有什么区别?

数组只能包含单个数据类型元素,而列表可以包含任何数据类型元素。
元组不能修改,元组计算更快,元组是括号。

7. 什么是lambda函数?

lambda函数也叫匿名函数,该函数可以包含任意数量的参数,但只能有一个执行操作的语句

8. [:: – 1}表示什么?

用于反转数组或序列的顺序。

9. python中的生成器是什么?

返回可迭代项集的函数称为生成器。

10. 什么是pickling和unpickling?

Pickling是将Python对象转换为字节流的过程,这个过程也被称为序列化。在这个过程中,Python对象被转换成一个可以写入文件或通过网络发送的格式。这个格式是跨平台的,意味着在不同的操作系统和架构之间,pickled的数据可以保持一致。
要pickle一个对象,你可以使用pickle模块中的dump函数。

11. 为什么使用* args,** kwargs?

*args:它用于函数定义中,允许函数接受任意数量的位置参数,这些参数被收集到一个名为args的元组中。
**kwargs:它允许函数接受任意数量的关键字参数,这些参数被收集到一个名为kwargs的字典中。

def sum_numbers(*args):
    total = 0
    for number in args:
        total += number
    return total

print(sum_numbers(1, 2, 3, 4, 5))  # 输出 15
def print_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_info(name="Alice", age=25, city="Wonderland")  # 输出:
# name: Alice
# age: 25
# city: Wonderland

12. 如何在Python中实现多线程?什么是多线程?

多线程是:在单个程序中并行执行多个任务。

在Python中实现多线程的步骤:
导入threading模块。
定义一个函数,这个函数将作为线程执行的任务。
创建threading.Thread对象,将目标函数和参数传递给它。
调用线程对象的start()方法来启动线程。
调用线程对象的join()方法来等待线程完成。

import threading

# 共享资源,初始值为0
counter = 0

# 定义一个函数,用于增加计数器的值
def increment():
    global counter
    for _ in range(1000000):
        counter += 1

# 创建多个线程,每个线程都会执行increment函数
threads = []
for i in range(10):  # 创建10个线程
    thread = threading.Thread(target=increment)
    thread.start()
    threads.append(thread)

# 等待所有线程完成
for thread in threads:
    thread.join()

print(f"最终计数器的值为: {counter}")
# ---------------------------
# 创建了10个线程,每个线程都会执行increment函数。由于这些线程并发运行,它们会尝试同时增加counter的值

需要注意的是,由于Python的全局解释器锁(GIL),在执行多线程时,同一时刻只允许一个线程执行Python字节码。这意味着在CPython实现中,多线程并不能有效地利用多核CPU的计算资源。因此,对于计算密集型任务,多进程(使用multiprocessing模块)可能是更好的选择。然而,对于I/O密集型任务,如网络请求或文件读写,多线程仍然是提高程序性能的有效方法。

13. 如何在一个function里面设置一个全局的变量?

def f():
	global x

14. python中的浮点数运算问题

判断浮点数的运行结果是否相等:

a = 0.1 b = 0.2 c = 0.3 assert a + b == c

本题考查的是计算机的浮点运算知识点。不仅是 python 语言,其他的编程语言也面临同样的问题:在进行浮点运算的时候,10 进制表示方式会丢掉它的精度,造成运算结果与实际结果不符合。
这是由于底层 CPU 和运算标准通过自己的浮点单位去执行算术时的特征决定的。看似有穷的小数, 在计算机的二进制表示里却是无穷的。
所以在进行高精度浮点运算的时候一定要注意,尤其是自动化测试过程中需要进行断言非常容易出错。

解决:使用Decimal()

from decimal import Decimal a = 0.1 b = 0.2 c = 0.3 assert Decimal(str(a)) +
Decimal(str(b)) == Decimal(str(c))

Decimal() 可以维持浮点数的精度,在金融领域和测试领域等精度要求高的行业有非常大的作用。 但是一定要注意: Decimal() 传的参数一定要是字符串类型,如果是数据类型会再次丢掉精度。

15. 列表扁平化和降维,(机器学习中可能用到)

有一个二维列表,降成普通的一维的。比如说柠檬班都会有学员分组,我们想通过分组信息去获取所有的学员名称。

groups = [['huahua', 'xiaojian'], ['musen', 'yuze'], ['keyou']] 
# 需要得到结果:
['huahua', 'xiaojian', 'musen', 'yuze', 'keyou']

解决:

# 最简单的方式想到循环:
names = [] for group in groups: for name in group:
names.append(name) print(names)

# 但是在面试的时候可能会加一些限制,比如让你用一行代码实现,这个时候就需要对 python 基础有进一步的理解了,比如说使用 sum 函数:
names = sum(groups, [])

# 因为sum可以:
a = sum([1,2,3], 0) # 0 + 1 + 2 + 3

16. 多重继承和python中的继承

python中的继承包括:单继承,多重继承,多级继承,分层继承(多个子类继承同一个父类),混合继承

多重继承(一个子类继承多个父类)经常用来出面试题。在这个考题中,C 类的父类 A 和 B 都实现了 run 方法,那在 C 的对象里到底是优先调用哪一个呢?

class A:
	def run(self):
		print("a is running")
class B:
	def run(self):
		print("b is running")
class C(A, B):
	pass
# 会打印什么???a is running
C().run()

菱形问题:

class A:
	def run(self):
		print("a running")
class B(A):
	pass
class C(A):
	def run(self):
		print("C running")
class D(B, C):
	pass
# 会打印什么???c running
D().run()

v型问题:(如果不让C继承于A)

class A:
	def run(self):
		print("a running")
class B(A):
	pass
class C:
	def run(self):
		print("C running")
class D(B, C): 
	pass
# 会打印什么???a running
D().run()

17. 什么是python的三元表达式

三元表达式提供了一种快速、简洁的方式来编写条件语句,而不需要使用完整的if…else…结构。

age = 18
is_adult = (age >= 18)
message = "未成年" if not is_adult else "成年"
print(message)  # 输出 "成年",因为 age >= 18

18. 什么是Flask

Flask是一个用Python编写的轻量级Web应用框架。它由Armin Ronacher开发,其设计哲学是尽可能保持简单和灵活,让开发者可以快速搭建基本的Web应用,同时也能够用于构建复杂的系统。Flask依赖于两个外部库:Werkzeug WSGI工具箱和Jinja2模板引擎。

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'

if __name__ == '__main__':
    app.run()

19. 解释python中的dir()函数

dir() 函数返回对象中的所有成员 (任何类型)

20. 什么是猴子补丁?

猴子补丁(Monkey Patching)是一个编程术语,指的是在运行时动态地修改已有的模块、类、函数或方法的行为。这种做法通常用于扩展或改变第三方库中的对象,而无需修改其源代码。猴子补丁可以在不破坏原始代码的情况下,为现有的软件添加新功能或修复bug。

# 假设我们有一个原始的模块,其中包含一个函数
class OriginalClass:
    def original_method(self):
        print("Original behavior")

# 现在我们想要添加一个新的方法,而不修改OriginalClass的源代码
def new_method(self):
    print("New behavior")

# 通过猴子补丁将新方法添加到OriginalClass中
OriginalClass.new_method = new_method

# 创建OriginalClass的实例,并调用新添加的方法
instance = OriginalClass()
instance.new_method()  # 输出 "New behavior"
# 同时,原始的方法仍然可用
instance.original_method()  # 输出 "Original behavior"

💡 需要注意的是,虽然猴子补丁操作简单,但它可能会影响代码的可读性和可维护性,尤其是当其他开发者不知道你已经修改了某个类或模块的行为时。此外,猴子补丁可能会导致意外的副作用,特别是当它被用于大型项目或复杂的代码库时。因此,在使用猴子补丁时,最好确保你的修改是安全的,并且有适当的文档记录,以便其他开发者了解你的更改。

21. Python 中标识符的命名规则?

  1. 只能以下划线或字母开头
  2. 之后的字符只能是数字或字母
  3. 不能用关键字作为变量名称
  4. python区分大小写

22. 如何删除字符串中的前置空格?

前置空格是第一个非空格字符前的所有空格,使用 lstrip() 函数来删除.
如果想去除后置空格,使用 rstrip() 函数。

23. 如何转化大小写?

lower()upper()
要检查字符串是否为全大写或全小写,使用 isupper() 和 islower() 函数
@ 和$这样的字符即满足大写也满足小写。

24. python中的pass语句有什么用?

我们在写代码时,有时可能只写了函数声明而没想好函数怎么写,但为了保证语法检查的正确必须输入一些东西。在这种情况下,我们使用 pass 语句。

25. 在python中,什么是闭包Closure?

闭包通常用于创建 返回函数的 函数。

def outer_function(x):
    def inner_function(y):
        return x + y
    return inner_function    # 返回inner_funtion这个函数

# 创建一个闭包,它将outer_function的局部变量x保存下来
closure = outer_function(10)   
# closure在这是一个函数,是outer返回的inner函数

# 调用闭包,它将保存的x值和传入的y值相加
print(closure(5))  # 输出 15 (10 + 5)

Python中的闭包:

  • Python的闭包通常是通过定义一个嵌套函数来创建的,外部函数可以返回内部函数,而内部函数可以访问外部函数的局部变量。
  • Python中的闭包通常用于实现装饰器,这是一种修改其他函数行为的高级技术。
  • Python的函数是一等公民,这意味着函数可以作为参数传递给其他函数,也可以作为返回值返回。
  • Python的闭包通常用于封装状态,创建私有变量,或者在函数式编程风格中使用。

JavaScript中的闭包:

  • JavaScript的闭包也是通过嵌套函数来创建的,但是JavaScript的函数在定义时就会捕获外围函数的词法环境(lexicalenvironment),即使外围函数已经执行完毕。
  • JavaScript中的闭包常用于创建私有变量,实现模块化,以及在异步编程中保持状态。
  • JavaScript的函数也是一等公民,并且可以作为对象处理,这使得函数和闭包在JavaScript中非常灵活。
  • 由于JavaScript运行在浏览器环境中,闭包的使用可能会受到单线程执行模型和事件循环的影响,特别是在处理异步操作和定时器时。

26. Python 中的运算符

算术运算符:

//,%,**:整除、取余、幂运算

square = 2 ** 3  # 结果为 8

关系 (比较) 运算符:> ==
赋值运算符:+=
逻辑运算符:and or not
位运算符:位运算符对整数的二进制位进行操作。这些运算符包括位与(&)、位或(|)、位异或(^)、位非(~)、左移(<<)和右移(>>)

a = 0b1010  # 10
b = 0b0101  # 5
bit_and = a & b  # 0b0000 (0)
bit_or = a | b  # 0b1011 (11)
bit_xor = a ^ b  # 0b0111 (7)
bit_not = ~a  # -11 (取反)
left_shift = a << 1  # 0b1100 (20)
right_shift = b >> 1  # 0b0010 (2) 俄罗斯方块

成员运算符:用于检查一个值是否存在于序列(如列表、元组、字符串)或集合中。

sequence = [1, 2, 3, 4, 5]
value_in_sequence = 3 in sequence  # True
value_not_in_sequence = 6 in sequence  # False

身份运算符:用于比较两个变量是否引用同一个对象。这些运算符包括恒等(is)和非恒等(is not)。

a = [1, 2, 3]
b = [1, 2, 3]
c = a
a_is_c = a is c  # True (a和c引用同一个列表)
a_is_not_b = a is not b  # True (a和b引用不同的列表)

27. 如何在 Python 使用多进制数字?

二进制数以0b或0B为前缀

binary_number = 0b1010
print(binary_number)  # 输出 10

八进制数以0o或0O为前缀

octal_number = 0o12
print(octal_number)  # 输出 10

十六进制数以0x或0X为前缀

hexadecimal_number = 0x0A
print(hexadecimal_number)  # 输出 10

Python提供了内置的bin(), oct(), hex()函数来将十进制数转换为二进制、八进制和十六进制字符串

decimal_to_binary = bin(10)  # 返回 '0b1010'
decimal_to_octal = oct(10)  # 返回 '0o12'
decimal_to_hexadecimal = hex(10)  # 返回 '0xa'

binary_to_decimal = int('0b1010', 2)  # 返回 10
octal_to_decimal = int('0o12', 8)  # 返回 10
hexadecimal_to_decimal = int('0xa', 16)  # 返回 10

28. 如何声明多个变量并赋值?

a, b, c = [1, 2, 3]
a, b = 1, 2
a, b = b, a  # 传统的元组解包
a, b = b, a = 2, 1  # Python 3.4+的语法

29. 什么是装饰器?

在Python中,装饰器(Decorator)是一种设计模式,用于修改或增强函数、方法或类的行为,而不需要直接改变其定义。装饰器通常表现为一个接受函数作为参数并返回一个新函数的可调用对象。

装饰器的使用非常广泛,它们可以用来日志记录、性能测试、事务处理、缓存等。装饰器的一个关键优势是它们提供了一种透明的方式来改变函数的行为,而不需要修改函数的原始代码。

装饰器的基本语法如下:

def decorator_function(original_function):
    def wrapper_function(*args, **kwargs):
        # 在调用原始函数之前的代码(例如:日志记录)
        result = original_function(*args, **kwargs)
        # 在调用原始函数之后的代码(例如:性能测试)
        return result
    return wrapper_function

@decorator_function
def function_to_decorate():
    pass

装饰器如果带参数,基本语法如下:

def decorator_with_args(decorator_arg1):
    def decorator_function(original_function):
        def wrapper_function(*args, **kwargs):
            # 使用 decorator_arg1
            return original_function(*args, **kwargs)
        return wrapper_function
    return decorator_function

@decorator_with_args('decorator_arg_value')
def function_to_decorate():
    # 函数体
    pass

举例:记录函数调用的时间戳和执行时间

import time

def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start_time = time.perf_counter()  # 记录开始时间
        result = func(*args, **kwargs)     # 调用原始函数
        end_time = time.perf_counter()    # 记录结束时间
        elapsed_time = end_time - start_time  # 计算执行时间
        print(f"{func.__name__} took {elapsed_time:.4f} seconds to execute.")
        return result
    return wrapper

@timing_decorator
def slow_function():
    time.sleep(2)  # 模拟一个耗时的操作
    return "Done"

# 现在当我们调用 slow_function() 时,装饰器会记录它的执行时间
result = slow_function()

# ----------------------------
# 输出slow_function took 2.0001 seconds to execute.

30. 如何提高python的运行效率?

  • 使用生成器
  • 利用Python的内置函数和库。内置函数通常比手写的函数更高效,因为它们是用C语言编写的。
  • 关键代码使用外部功能包(Cython,pylnlne,pypy,pyrex);
  • 针对循环的优化–尽量避免在循环中访问变量的属性
  • 使用矢量化操作代替循环。例如,使用NumPy等库进行数组操作,可以利用底层的C语言实现来提高效率。
  • 使用并行计算。对于计算密集型任务,可以使用multiprocessing模块来创建多个进程,实现并行计算。

31. 常用Linux命令

ls -l /home/user  # 以长格式列出/home/user目录下的文件和目录
help cd  # 显示cd命令的帮助信息
cd /etc  # 切换到/etc目录
cd ~  # 切换到当前用户的主目录
more /var/log/syslog  # 逐页显示syslog文件的内容
clear  # 清空当前终端屏幕
mkdir new_folder  # 在当前目录下创建一个名为new_folder的新目录
pwd  # 显示当前工作目录的路径
rm file.txt  # 删除名为file.txt的文件
rm -r directory  # 递归删除名为directory的目录及其内容
grep "error" log.txt  # 在文件log.txt中搜索"error"字符串
find /home -name "*.txt"  # 搜索/home目录下所有扩展名为.txt的文件
mv old_file.txt new_file.txt  # 将文件old_file.txt重命名为new_file.txt
su - root  # 切换到root用户
date  # 显示当前系统日期和时间

32. python中的yield是什么?

在Python中,yield是一个关键字,用于创建生成器(generator)。生成器是一种特殊的迭代器,它允许你在一个函数中定义一个迭代算法,而不需要一次性地计算出所有的结果。相反,生成器在每次迭代时计算并返回下一个结果,这使得它在处理大数据集或需要按需计算的场景中非常有用。

当你在一个函数中使用yield时,Python会将该函数转换为生成器。每次调用生成器的next()方法或者在生成器上进行迭代时,函数会执行到yield语句,然后暂停执行,返回yield后面表达式的值,并在那里保存当前函数的状态(包括局部变量和指令指针)。下一次迭代时,函数会从上次暂停的地方继续执行。

def generator_with_send(value):
    print(f"Received value: {value}")
    result = yield
    print(f"Sending result: {result})

# 创建生成器对象并开始迭代
gen_with_send = generator_with_send("Hello")

# 发送值给生成器并接收返回值
print(next(gen_with_send))  # 输出 "Received value: Hello"
print(gen_with_send.send("World"))  # 输出 "Sending result: World"

32. 谈一下python的GIL(Global Interpreter Lock)

全局解释器锁:

  • Python代码的执行由Python 虚拟机(也叫解释器主循环,CPython版本)来控制,Python在设计之初就考虑到要在解释器的主循环中,同时只有一个线程在执行,即在任意时刻,只有一个线程在解释器中运行。
  • 对Python虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。如果线程运行过程中遇到耗时操作,则解释器锁解开,使其他线程运行。所以在多线程中,线程的运行仍是有先后顺序的,并不是同时进行。
  • 多进程中因为每个进程都能被系统分配资源,相当于每个进程有了一个python解释器,所以多进程可以实现多个进程的同时运行,缺点是进程系统资源开销大。
  • 在多线程环境中,Python 虚拟机按以下方式执行:
  • \1. 设置GIL
  • \2. 切换到一个线程去运行
  • \3. 运行: a.指定数量的字节码指令,或者 b. 线程主动让出控制(可以调用time.sleep(0))
  • \4. 把线程设置为睡眠状态
  • \5.解锁GIL
  • \6. 再次重复以上所有步骤

33. 面向对象中的_new_ 和 _init_的区别

  • new是一个在Python中由类继承而来的静态方法(即使在Python 3中,它不是一个关键字,但习惯上按照静态方法的约定来使用)。它的主要作用是在创建类的新实例时分配内存空间。 new方法在__new__的实现中被调用,通常不需要直接调用。new方法返回一个实例对象,但此时对象还没有进行初始化。 它通常用于定制对象的创建过程,比如处理继承关系、单例模式等高级用法。
  • __init__是一个特殊的方法,也称为构造器或初始化方法。
    它在对象创建后、对象开始使用之前被自动调用用于初始化对象的状态
    __init__方法的主要作用是设置对象在开始使用前需要的一些初始状态或执行一些启动配置。
    接受self参数,代表即将被创建的实例对象本身,以及其他参数和关键字参数,用于传递给对象实例化时所需的数据。

  • 在Python中,当你创建一个类的实例时,首先会调用__new__方法来创建对象,然后调用__init__方法来初始化对象。
  • 通常情况下,你不需要重写__new__方法,除非你需要对类的创建过程进行定制。而__init__方法则是在定义类时经常需要重写的,以确保对象在创建时拥有正确的初始状态。

34. 简述with方法打开处理文件帮我我们做了什么?

打开文件在进行读写的时候可能会出现一些异常状况,如果按照常规的f.open写法,我们需要try,except,finally,做异常判断,并且文件最终不管遇到什么情况,都要执行finally f.close()关闭文件,
with方法帮我们实现了finally中f.close(当然还有其他自定义功能)

35. map()函数

  • 列表[1,2,3,4,5],请使用map()函数输出[1,4,9,16,25],并使用列表推导式提取出大于10的数,最终输出[16,25]?
  • map()函数第一个参数是fun,第二个参数是一般是list,第三个参数可以写list,也可以不写,根据需求。

36. 常用的正则表达式

  • .*? (非贪婪匹配)
  • .* (贪婪匹配)

37. python中断言方法

# 检查列表长度是否等于特定值
my_list = [1, 2, 3]
assert len(my_list) == 3, "列表长度不等于3"

如果my_list的长度不等于3,将会触发断言错误,并显示相应的错误信息。

38. 列出python中可变数据类型和不可变数据类型

不可变数据类型:数值型、字符串型string和元组tuple不允许变量的值发生变化,如果改变了变量的值,相当于是新建了一个对象,
**但是!**对于相同的值的对象,在内存中则只有一个对象(一个地址),如下图(用id()方法可以打印对象的id)。

a = 3
b = 3
id(a) #1365598496
id(b) #1365598496

可变数据类型:列表list和字典dict;允许变量的值发生变化,即如果对变量进行append、+=等这种操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化,
**但是!**对于相同的值的不同对象,在内存中则会存在不同的对象,即每个对象都有自己的地址,相当于内存中对于同值的对象保存了多份,这里不存在引用计数,是实实在在的对象。

a = [1,2]
b = [1,2]
id(a) #427336
id(b) #321544

39. Join() 迭代

x="abc"
y="def"
z=["d","e","f"]

m=x.join(y) # dabceabcf
n=x.join(z) # dabceabcf

40. [1,2,3]+[4,5,6]的结果是多少?

两个列表相加,等价于extend

a=[1,2,3]
b=[4,5,6]
a+b # [1,2,3,4,5,6]

41. python递归的最大层数

在Python中,递归的最大层数是由sys模块中的getrecursionlimit()函数返回的值决定的,这个值默认通常设置为1000。但是,这个限制是可以被修改的,通过sys.setrecursionlimit()函数可以设置一个新的限制值。

然而,增加递归层数的上限可能会增加程序崩溃的风险,因为Python的递归不会进行尾递归优化,且每个递归调用都会占用堆栈空间。

请注意,递归层数的增加可能会导致程序运行速度变慢,或者在极端情况下,导致栈溢出错误(Stack Overflow)。因此,在实际应用中,应当谨慎地调整递归层数的上限。

42. 三元运算符

res = 'a' if condition else 'b'
x = 10
y = "大于10" if x > 10 else "小于等于10"
print(y)  # 输出 "小于等于10"

如果是JS:

var x = 10;
var y = x > 10 ? "大于10" : "小于等于10";
console.log(y);  // 输出 "小于等于10"

43. python的read() 、readline()、readlines()、xreadlines()

  • read()会读取整个文件,将读取到底的文件内容放到一个字符串变量,返回str类型。
  • readline()读取一行内容,放到一个字符串变量,返回str类型。
  • readlines() 读取文件所有内容,按行为单位放到一个列表中,返回list类型。
  • xreadlines()返回一个生成器,来循环操作文件的每一行。

44. 一行代码选出列表里面的不重复元素

unique_elements = list(set(my_list))

如果顺序很重要:

unique_elements = list(dict.fromkeys(my_list))

45. print 格式化

 print("我叫{},今年{}岁了".format("小李", 20))

👍网络编程与并发

46. 面向对象深度优先和广度优先是什么?

在计算机科学中,深度优先搜索(Depth-First Search, DFS)和广度优先搜索(Breadth-First Search, BFS)是两种常用的图遍历算法,它们在面向对象编程(Object-Oriented Programming, OOP)中同样适用,尤其是在处理图结构数据时,如社交网络、网络爬虫、决策树等场景。

在面向对象的上下文中,DFS和BFS可以用于遍历对象之间的关系,如遍历类的对象图、处理类继承关系等。这两种搜索算法在许多领域都非常有用,包括搜索引擎优化、社交网络分析、解决迷宫问题等。

47. 简述 OSI 七层协议

OSI是Open System Interconnection的缩写,意为开放式系统互联。

  • 1、物理层 主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与 模数转换)。这一层的数据叫做比特。
  • 2、数据链路层 定义了如何让格式化数据以进行传输,以及如何让控制对物理介质的访问。这一层通常还提供错误检测和纠正, 以确保数据的可靠传输。
  • 3、网络层 在位于不同地理位置的网络中的两个主机系统之间提供连接和路径选择。Internet的发展使得从世界各站点访问信息的用户数大大增加,而网络层正是管理这种连接的层。
  • 4、运输层 定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(transmission control protocol –传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据) UDP(user datagram protocol–用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据 量小的数据,如QQ聊天数据就是通过这种方式传输的)。主要是将从下层接收的数据进行分段和传输,到达目 的地址后再进行重组。常常把这一层数据叫做段。
  • 5、会话层通过运输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)
  • 6、表示层可确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取。例如,PC程序与另一台计算机进行通信,其中一台计算机使用扩展二一十进制交换码(EBCDIC),而另一台则使用美国信息交换标准码(ASCII)来表示相同的字符。如有必要,表示层会通过使用一种通格式来实现多种数据格式之间的转换。
  • 7、应用层是最靠近用户的OSI层。这一层为用户的应用程序(例如电子邮件、文件传输和终端仿真)提供网络服务。

48. 什么是C/S和B/S架构?

C/S架构软件(即客户机/服务器模式)分为客户机和服务器两层。
优点:

  • a. 客户端和服务器直接相连。点对点的连接方式更安全,可以直接操作本地文本,比较方便。
  • b.客户端可以处理一些逻辑事务。可以进行数据处理和数据存储,提供一定的帮助。
  • c. 客户端直接操作界面。

缺点:

  • a. C/S架构适用于局域网,对网速的要求比较高。
  • b. 客户端界面缺乏通用性,且当业务更改时就需要更改界面,重新编写。
  • c. 随着用户数量的增多,会出现通信拥堵、服务器响应速度慢等情况。
  • d. 系统的维护也比较麻烦。

C/S架构的软件数不胜数,从办公的OFFICE,WPS,WINRAR到杀毒软件如金山,瑞金再到我们的娱乐软件,如播放器,QQ,微信等,无处不见C/S架构.


B/S它是C/S架构的一种改进,
可以说属于三层C/S架构。主要是利用了不断成熟的WWW浏览器技术,用通用浏览器就实现了原来需要复杂专用软件才能实现的强大功能,并节约了开发成本,是一种全新的软件系统构造技术。

优点:

  • a. 浏览器和数据库服务器采用多对多的方式连接。因此适合在广域网里实现巨大的互联网,甚至是全球网,有
    着很强大的信息共享性。
  • b. 浏览器只处理一些简单的逻辑事务,负担小。
  • c. 数据都集中存放在数据库服务器,所以不存在数据不一致现象。
  • d. 随着服务器负载的增加,可以平滑地增加服务器的个数并建立集群服务器系统,然后在各个服务器之间做负
    载均衡。
  • e. B/S建立在广域网上,所以需要的网速要求不高。
  • f. 不需要安装客户端,只要能连上网,就能随时随地的浏览页面。
  • g. 能有效地保护数据平台和管理访问权限,确保服务器数据库的数据安全。

缺点:

  • a. 服务器承担着重要的责任,数据负荷较重。一旦发生服务器“崩溃”等问题,后果不堪设想。
  • b. 页面需要不断地动态刷新,当用户增多时,网速会变慢。

WEBQQ根本不需要安装客户端,只需要有浏览器就可以进行聊天交互了.

  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值