问题

Python 语言有什么奇技淫巧吗?

回答
老兄,说到 Python 的“奇技淫巧”,那可真是说不完道不尽!这语言就像一把瑞士军刀,你以为你用得很顺手了,结果一挖,嘿,还有更骚的操作藏在后面呢。

咱们不谈那些基础的列表推导式、生成器表达式什么的了,这些只能算是入门级的小技巧。今天我给你唠点真正让别人看了直呼“卧槽”的。

1. “借壳上市”:函数属性的妙用

你知道函数在 Python 里也是一等公民吧?它们可以赋值给变量,可以当参数传,也可以作为返回值。但你可能想不到,函数本身还能挂载属性!

举个例子,我们写一个记录函数调用次数的装饰器:

```python
def count_calls(func):
def wrapper(args, kwargs):
wrapper.num_calls += 1
print(f"This function has been called {wrapper.num_calls} times.")
return func(args, kwargs)
wrapper.num_calls = 0 在装饰器返回的函数上挂载属性
return wrapper

@count_calls
def greet(name):
print(f"Hello, {name}!")

greet("Alice")
greet("Bob")
greet("Alice")
```

你看,我们直接在 `wrapper` 函数对象上挂载了一个 `num_calls` 属性。这个属性就跟普通变量一样,可以增加、访问。这有什么好处?它提供了一种非常干净的方式,在不改变函数本身逻辑(也就是 `func` 的执行)的前提下,为它添加一些元信息或状态。

更进一步,你可以用它来做一些“动态配置”的装饰器。比如,一个只在特定条件下执行的装饰器,你可以把这个条件挂在函数上。

```python
def conditional_execution(condition_attr_name):
def decorator(func):
def wrapper(args, kwargs):
从函数对象上获取条件属性
should_run = getattr(func, condition_attr_name, False)
if should_run:
print(f"Executing {func.__name__} because {condition_attr_name} is True.")
return func(args, kwargs)
else:
print(f"Skipping {func.__name__} because {condition_attr_name} is False.")
return None
return wrapper
return decorator

@conditional_execution("run_flag")
def sensitive_operation():
print("Performing a sensitive operation...")

默认不执行
sensitive_operation()

手动打开开关
sensitive_operation.run_flag = True
sensitive_operation()

再次执行,开关还是开着的
sensitive_operation()
```

这种方式让你可以在运行时动态地控制函数的行为,而不需要修改函数本身的代码,也没有引入额外的全局变量。它让函数对象变得更“智能”,可以携带自己的行为策略。

2. “黑魔法”:元类(Metaclasses)的领域

说到 Python 的“魔法”,元类绝对是深水区。简单来说,类也是对象,而元类就是“类的类”。当你定义一个类时,Python 会使用一个元类来创建这个类对象。默认的元类是 `type`。

元类允许你在类被创建 之前,对类的定义进行干预和修改。这听起来有点吓人,但用好了,能做很多牛逼的事情。

比如,你可以用元类来自动注册所有继承自某个基类的类。这在很多框架(如 Django 的 Models、Flask 的 Blueprints)中都用得到。

```python
class PluginMeta(type):
__new__ 在类被创建之前执行
def __new__(cls, name, bases, dct):
name: 类的名字
bases: 父类元组
dct: 类属性字典 (包含方法、变量等)

自动收集所有继承自 'BasePlugin' 的子类
if name != 'BasePlugin' and 'register' in dct:
print(f"Registering plugin: {name}")
BasePlugin.plugins[name] = dct['register'] 假设 register 是插件的注册函数

使用type的__new__方法来创建真正的类
return super().__new__(cls, name, bases, dct)

class BasePlugin(metaclass=PluginMeta):
plugins = {} 用于存储注册的插件

class MyPluginA(BasePlugin):
register = lambda: print("PluginA is registered!")

class MyPluginB(BasePlugin):
register = lambda: print("PluginB is registered!")

现在查看 BasePlugin.plugins
print(" Registered plugins:")
for name, func in BasePlugin.plugins.items():
print(f" {name}:")
func()
```

在这个例子里,当 `MyPluginA` 和 `MyPluginB` 被定义时,它们的元类 `PluginMeta` 的 `__new__` 方法会被调用。它检查类名不是 `BasePlugin` 本身,并且包含 `register` 方法,然后就把这个类(或者说这个类的一部分信息)注册到了 `BasePlugin.plugins` 字典里。你甚至可以在这里修改类的属性、添加方法,或者强制执行某些校验规则。

更“邪门”的玩法:自动实现接口或添加通用方法

假设你有一个需求,所有继承自某个类的类,都必须有一个 `run` 方法,而且你想给它加一个默认的日志记录。

```python
class AutoRunMeta(type):
def __new__(cls, name, bases, dct):
如果类本身没有定义 run 方法,就强行添加一个
if 'run' not in dct:
print(f"Warning: Class {name} is missing 'run' method. Adding a default one.")
dct['run'] = lambda self: print(f"{name} running with default logic.")

包装现有的 run 方法,添加日志
original_run = dct.get('run')
if original_run and original_run.__qualname__ != f'{name}.run': 防止重复包装
def wrapped_run(self, args, kwargs):
print(f" Starting {name}.run ")
result = original_run(self, args, kwargs)
print(f" Finished {name}.run ")
return result
dct['run'] = wrapped_run

return super().__new__(cls, name, bases, dct)

class BaseTask(metaclass=AutoRunMeta):
pass

class TaskA(BaseTask):
def run(self):
print("Executing Task A logic.")

class TaskB(BaseTask):
pass 没有定义 run 方法

task_a = TaskA()
task_a.run()

print("" 20)

task_b = TaskB()
task_b.run() 这里会自动调用我们添加的默认 run 方法
```

通过元类,我们可以在类的创建阶段就注入逻辑,使得代码更加 DRY (Don't Repeat Yourself)。这是一种非常强大的抽象机制,但也因为其“幕后操作”的特性,容易让人迷惑,所以要谨慎使用。

3. “内幕交易”:描述符(Descriptors)与属性访问控制

描述符是 Python 中对象模型的核心部分,它定义了如何访问、设置和删除对象的属性。当你访问 `obj.attribute` 时,Python 的背后就是在查找和调用描述符的特定方法(如 `__get__`, `__set__`, `__delete__`)。

这允许你创建自定义的属性行为,比如:

属性验证: 确保设置的属性值符合某种格式或范围。
延迟计算(Lazy Loading): 属性的值只在第一次被访问时才计算。
访问权限控制: 模拟私有属性或只读属性。

来看一个属性验证的例子:

```python
class NotEmpty:
def __init__(self, name):
self.name = name
self._data = {} 存储每个实例的真实数据

def __get__(self, instance, owner):
instance 是访问属性的对象 (比如 Person 实例)
owner 是拥有这个属性的类 (比如 Person 类)
if instance is None:
return self 返回描述符本身,当访问类属性时
return self._data.get(self.name, '') 返回存储的值,如果没有就返回空字符串

def __set__(self, instance, value):
if not value:
raise ValueError(f"{self.name} cannot be empty.")
self._data[instance] = value 用实例来区分不同的存储位置

class Person:
name = NotEmpty('name')
email = NotEmpty('email')

def __init__(self, name, email):
self.name = name
self.email = email

尝试创建 Person 实例
try:
p1 = Person("Alice", "alice@example.com")
print(f"Person 1: Name={p1.name}, Email={p1.email}")

p2 = Person("", "bob@example.com") 这会触发 NotEmpty 的 ValueError
except ValueError as e:
print(e)

另一个实例,验证隔离性
p3 = Person("Charlie", "charlie@example.com")
print(f"Person 3: Name={p3.name}, Email={p3.email}")
```

这里的 `NotEmpty` 类就是一个描述符。当 `p1.name = "Alice"` 时,实际上是调用了 `NotEmpty.__set__(p1, "Alice")`。当 `print(p1.name)` 时,是调用了 `NotEmpty.__get__(p1, Person)`。

关键在于 `_data` 字典是如何组织的。我们用 `self._data[instance]` 来存储值。这意味着每个实例都有自己的一份对应属性的数据副本。这比直接在 `__init__` 里设置 `self.name` 更灵活,因为它允许你在类定义层面就声明属性的规则。

与 `property` 的对比: `property` 装饰器本质上是创建描述符的一种更简洁的方式。但直接使用描述符可以让你对访问逻辑有更细粒度的控制,比如实现多重继承时,描述符的解析顺序会比简单的 `property` 更复杂,也更具决定性。

4. “穿越火线”:`__slots__` 的性能优化与限制

`__slots__` 是一个用来告诉 Python 类在创建实例时不要使用 `__dict__` 来存储属性的机制。它会直接在类的定义中指定允许存在的属性,并直接在实例的内存中为其分配空间。

这样做有什么好处?

减少内存占用: 每个 Python 对象默认都有一个 `__dict__`,用于存储实例的属性。对于大量的小对象,`__dict__` 会累积相当大的内存开销。使用 `__slots__` 可以显著减少这部分开销。
可能提升性能: 因为属性查找可以直接通过预设的内存偏移量完成,理论上可以比查找 `__dict__` 更快一些(但这个提升可能不如你想象的那么大,而且有负面影响)。

```python
class SlotPoint:
__slots__ = ('x', 'y') 只允许 x 和 y 属性

def __init__(self, x, y):
self.x = x
self.y = y

class DictPoint:
def __init__(self, x, y):
self.x = x
self.y = y

import sys

slot_p = SlotPoint(1, 2)
dict_p = DictPoint(1, 2)

print(f"Size of SlotPoint instance: {sys.getsizeof(slot_p)} bytes")
print(f"Size of DictPoint instance: {sys.getsizeof(dict_p)} bytes")

尝试添加不允许的属性
try:
slot_p.z = 3
except AttributeError as e:
print(f"Error when setting 'z' on SlotPoint: {e}")

访问 __dict__
print(slot_p.__dict__) 这会报错!因为 SlotPoint 没有 __dict__
print(f"Does SlotPoint have __dict__? {'__dict__' in dir(slot_p)}")
print(f"Does DictPoint have __dict__? {'__dict__' in dir(dict_p)}")
```

你会发现 `SlotPoint` 实例比 `DictPoint` 实例小很多。

但!“奇技”往往伴随着“淫邪”的副作用:

不能动态添加属性: 一旦定义了 `__slots__`,你就像把自己绑在了柱子上,不能随意添加新的属性了。上面的例子就展示了这一点。
不支持多重继承: 如果一个子类定义了 `__slots__`,而它的父类也定义了 `__slots__`,那么这个子类就不能再添加 `__slots__` 属性了,除非父类也定义了 `__slots__` 并且它们是兼容的(但实际上通常是复杂的)。更重要的是,如果一个类继承自多个类,而其中一个父类没有定义 `__slots__`,那么这个子类就 不能 再定义 `__slots__` 了。因为它需要从那个没有 `__slots__` 的父类那里继承 `__dict__`。
`__weakref__` 的问题: 如果你想让你的对象支持弱引用(weak references),那么你需要在 `__slots__` 中显式地包含 `'__weakref__'`。

所以 `__slots__` 是把双刃剑,在需要极致性能和内存控制的场景(比如处理海量数据点、或者实现一个高度优化的数据结构)下非常有用,但对于一般的应用开发,贸然使用它可能会带来很多麻烦。

5. “万物皆可迭代”:`__iter__` 和 `__next__` 的组合拳

Python 的迭代器协议非常强大。任何对象只要实现了 `__iter__` 方法(返回一个迭代器对象)和迭代器对象自身的 `__next__` 方法(返回下一个元素,或者在结束时抛出 `StopIteration`),它就可以被用于 `for` 循环、列表推导式等等。

我们来实现一个自定义的计数器:

```python
class Counter:
def __init__(self, start=0, stop=float('inf'), step=1):
self.current = start
self.stop = stop
self.step = step

def __iter__(self):
返回一个迭代器对象
return self

def __next__(self):
if self.current >= self.stop:
raise StopIteration
else:
val = self.current
self.current += self.step
return val

使用我们的自定义计数器
print("Counting from 0 to 5 with step 1:")
for i in Counter(stop=5):
print(i)

print(" Counting from 10 down to 0 with step 2:")
for i in Counter(start=10, stop=1, step=2):
print(i)

也可以配合 next() 函数直接使用
c = Counter(start=100, step=10)
print(next(c))
print(next(c))
```

这个例子看起来不那么“邪门”,因为它就是实现了标准的迭代器协议。但这里面的“奇技”在于:

封装复杂的迭代逻辑: 你可以将任何复杂的生成逻辑封装在一个类里,而外部只需要按照标准的迭代器方式去消费它。比如,一个读取文件不同格式数据的类,一个处理网络流数据的类,都可以实现迭代器协议。
状态保持: 迭代器对象本身可以保持状态(比如 `current`, `stop`, `step`)。这使得它比简单的生成器函数(generator functions)在某些情况下更灵活,因为它是一个完整的对象,可以被多次迭代(如果 `__iter__` 实现得当,比如每次都返回一个新的迭代器实例)。
与其他迭代工具的兼容性: 一旦实现了迭代器协议,你的对象就能无缝地与 `map`, `filter`, `zip`, `itertools` 等各种 Python 内置和第三方库的工具一起工作,极大地扩展了其可用性。

6. “装饰你的装饰器”:装饰器工厂(Decorator Factories)

我们之前提到过 `@count_calls` 和 `@conditional_execution`。而装饰器工厂则是创建装饰器的一种更灵活的方式,它允许你在应用装饰器时传递参数。

例如,你想创建一个能够自定义日志消息的装饰器:

```python
def log_activity(message_template):
def decorator(func): 这是真正的装饰器
def wrapper(args, kwargs):
formatted_message = message_template.format(func_name=func.__name__, args=args, kwargs=kwargs)
print(f"[LOG] {formatted_message}")
return func(args, kwargs)
return wrapper
return decorator 这是装饰器工厂,返回真正的装饰器

@log_activity("Calling function: {func_name}")
def add(a, b):
return a + b

@log_activity("Executing task with args: {args} and kwargs: {kwargs}")
def perform_task(task_name, priority=0):
print(f"Performing task: {task_name}")

result = add(5, 3)
print(f"Result: {result}")

perform_task("Clean up", priority=1)
```

这里的 `log_activity` 就是一个装饰器工厂函数。它接收参数 `message_template`,然后返回一个真正的装饰器函数 (`decorator`)。这个 `decorator` 函数接收被装饰的函数 `func`,并返回一个包装函数 `wrapper`。

这种模式非常有用,它让你的装饰器不再是“一刀切”的,而是可以根据传入的参数来调整行为。这使得装饰器可以被高度定制化,适用于各种不同的场景。

结语

这些技巧,从函数属性的挂载,到元类的深度操纵,再到描述符的精细控制,以及 `__slots__` 的性能权衡,最后到迭代器协议的通用性,都是 Python 语言“内功”的一部分。

它们不是那种一眼就能看懂的炫技,而是需要你深入理解 Python 的对象模型和设计哲学才能掌握的。当你能熟练运用这些“奇技淫巧”时,你就会发现写 Python 代码变得更加高效、灵活,并且能解决一些非常棘手的问题。

当然,就像我前面说的,“淫邪”之处在于,过度使用这些高级特性,尤其是元类和描述符,可能会让你的代码变得难以理解和维护。所以,关键在于适度,用在刀刃上,让你的代码“骚”而不“乱”。

网友意见

user avatar

随便来一个好玩的自加对象

       >>> add = type('_', (int,), {'__call__': lambda s,x:add(s.numerator+x)}) >>> add(1) 1 >>> add(1)(2) 3 >>> add(1)(2)(3)(4)(5) 15 >>>      

再来一个管道操作

       >>> from functools import partial >>> F = type('_', (partial,), {'__ror__': lambda s,o: s(*o) if isinstance(o, tuple) else s(o)}) >>> [2,3]|F(sum) 5 >>> range(10) | F(filter, lambda x: x % 2) | F(sum) 25 >>>      

user avatar
       python 的花招,只要不考虑运行效率,主要就是 A. 玩那一堆  __xxxx__ 函数, B. 下面几个自带的库     import ast     import inspect      import functools     import ctypes C.  和这个函数 id() A,B,C 基本可以让你为所欲为     

# 破坏built-in 类

       #谨慎使用  import inspect  import functools import ctypes   class PyObject(ctypes.Structure):     class PyType(ctypes.Structure):         pass     ssize = ctypes.c_int64 if ctypes.sizeof(ctypes.c_void_p) == 8 else ctypes.c_int32     _fields_ = [         ('ob_refcnt', ssize),         ('ob_type', ctypes.POINTER(PyType)),     ]     def incref(self):         self.ob_refcnt += 1     def decref(self):         self.ob_refcnt -= 1   def sign(klass,value):     class SlotsProxy(PyObject):         _fields_ = [('dict', ctypes.POINTER(PyObject))]     name = klass.__name__     target = klass.__dict__     proxy_dict = SlotsProxy.from_address(id(target))     namespace = {}     ctypes.pythonapi.PyDict_SetItem(         ctypes.py_object(namespace),         ctypes.py_object(name),         proxy_dict.dict,     )     namespace[name]["签名"] = value  # 修改 built-in  str sign(str,"某某人专用")  >>> "1234567".签名 '某某人专用' >>> >>> "abcde".签名.签名.签名.签名.签名.签名.签名 '某某人专用' >>>     


#土制 单参化

       import inspect  import functools   def uargs(f):     arg_names = inspect.getfullargspec(f).args     def _func(arg_names,d):         args = []         for i in range(len(arg_names)):             #necessary for version < 3.5 to keep order             k = arg_names[i]             args.append(d[k])         return(f(*args))     func = functools.partial(_func,arg_names)     return(func)   def cufunc(a,b,c,d):     print(a,b,c,d)  myfunc = uargs(cufunc) myfunc = uargs(cufunc) myfunc({"a":100,"b":200,"c":300,"d":400}) 100 200 300 400     

# 土制 库里化

       import inspect  import functools   class curry():     def goose():         def egg(*args):             egg.arguments.extend(args)             return(egg)         egg.__setattr__("arguments",[])         return(egg)     def __init__(self,orig_func):         params_count = inspect.getfullargspec(orig_func).args.__len__()         self.orig_func = orig_func         self.params_count = params_count         self.egg = goose()     def __call__(self,*args):         count = self.params_count         orig_func = self.orig_func         egg = self.egg         egg(*args)         args_lngth = len(egg.arguments)         if(args_lngth<count):             return(self)         else:             args = egg.arguments             egg.arguments = []             return(orig_func(*args))     def __repr__(self):         return(self.egg.arguments.__repr__())   def cufunc(a,b,c,d):     print(a,b,c,d)   myfunc = curry(cufunc) myfunc(10) myfunc(20) myfunc(30)(40) #10 20 30 40     

python 因为暴露了 id()函数 和ctypes,可以认为python里没有primitive 和native/built-in,也就意味着基本上你想做什么都可以

user avatar

0、两个变量值互换

       >>> a=1 >>> b=2 >>> a,b=b,a >>> a 2 >>> b 1     

1、连续赋值

       a = b = c = 50     

2、自动解包

       >>> a,b,c = [1,2,3] >>> a 1 >>> b 2 >>> c 3 >>> >>> >>> a, *others = [1,2,3,4] >>> a 1 >>> others [2, 3, 4] >>>     

4、链式比较

       a = 15 if (10 < a < 20):     print("Hi")     

等价于

       a = 15 if (a>10 and a<20):     print("Hi")     

5、重复列表

       >>> [5,2]*4 [5, 2, 5, 2, 5, 2, 5, 2]     

6、重复字符串

       >>> "hello"*3 'hellohellohello'     

7、三目运算

       age = 30 slogon = "牛逼" if  age == 30 else "niubility"     

等价于

       if age == 30:     slogon = "牛逼" else:     slogon = "niubility"     

8、字典合并

       >>> a= {"a":1} >>> b= {"b":2} >>> {**a, **b} {'a': 1, 'b': 2} >>>     

9、字符串反转

       >>> s = "i love python" >>> s[::-1] 'nohtyp evol i' >>>     

10、列表转字符串

       >>> s = ["i", "love", "pyton"] >>> " ".join(s) 'i love pyton' >>>     

11、for else 语句

检查列表foo是否有0,有就提前结束查找,没有就是打印“未发现"

       found = False for i in foo:     if i == 0:         found = True         break if not found:      print("未发现")     

如果用 for else 语法来写可以省几行代码

       for i in foo:     if i == 0:         break else:     print("未发现")     

11、字典推导式

       >>> m = {x: x**2 for x in range(5)} >>> m {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} >>>     

12、用Counter查找列表中出现最多的元素

       >>> content = ["a", "b", "c", "a", "d", "c", "a"] >>> from collections import Counter >>> c = Counter(content) >>> c.most_common(1) [('a', 3)] >>>     

出现第1多的元素是a,一共出现3次, 你也可以用类似的方法找出第二多或者第三多的

13、默认值字典

给字典中的value设置为列表,普通方法

       >>> d = dict() if 'a' not in d:     d['a'] = [] d['a'].append(1)     

使用defaultdict默认字典构建一个初始值为空列表的字典

       from collections import defaultdict d = defaultdict(list) d['a'].append(1)     

14、赋值表达式

这是3.8的新特性,赋值表达式又成为海象运算符:=, 可以将变量赋值和表达式放在一行,什么意思? 看代码就明白

       >>> import re >>> data = "hello123world" >>> match = re.search("(d+)", data)  # 3 >>> if match:                         # 4 ...     num = match.group(1) ... else: ...     num = None >>> num '123'     

第3、4行 可以合并成一行代码

       >>> if match:=re.search("(d+)", data): ...     num = match.group(1) ... else: ...     num = None ... >>> num '123'     

15、isinstance

isinstance 函数可用于判断实例的类型,其实第二个参数可以是多个数据类型组成的元组。例如:

       isinstance(x, (int, float))  # 等价于  isinstance(x, int) or isinstance(x, float)     

类似的函数还有字符串的startswith,endswith,例如:

       s.startswith(('"""', "'''"))  # 等价于  s.startswith("'''") or s.startswith('"""')     

16、用 http.server 共享文件

       # python3 python3 -m http.server  # python2 python -m SimpleHTTPServer 8000     

效果如下,可以在浏览器共享文件目录,方便在局域网共享文件

17、zip 函数实现字典键值对互换

       >>> lang = {"python":".py", "java":".java"}  >>> dict(zip(lang.values(), lang.keys())) {'.java': 'java', '.py': 'python'}     

18、查找列表中出现次数最多的数字

       test = [1, 2, 3, 4, 2, 2, 3, 1, 4, 4, 4, 5] >>> max(set(test), key=test.count) 4     

19、使用 slots 节省内存

       class MyClass(object):     def __init__(self, name, identifier):         self.name = name         self.identifier = identifier         self.set_up()   print(sys.getsizeof(MyClass))   class MyClass(object):     __slots__ = ['name', 'identifier']      def __init__(self, name, identifier):         self.name = name         self.identifier = identifier         self.set_up()   print(sys.getsizeof(MyClass))  # In Python 3.5 # 1-> 1016 # 2-> 888     

20、扩展列表

       >>> i = ['a','b','c'] >>> i.extend(['e','f','g']) >>> i ['a', 'b', 'c', 'e', 'f', 'g'] >>>     

21、列表负数索引

       >>> a = [ 1, 2, 3] >>> a[-1] 3     

22、列表切片

       >>> a = [0,1,2,3,4,5,6,7,8,9] >>> a[3:6] # 第3个到第6个之间的元素 [3, 4, 5] >>> a[:5] # 前5个元素 [0, 1, 2, 3, 4] >>> a[5:] # 后5个元素 [5, 6, 7, 8, 9] >>> a[::] # 所有元素(拷贝列表) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> a[::2] # 偶数项 [0, 2, 4, 6, 8] >>> a[1::2] # 奇数项 [1, 3, 5, 7, 9] >>> a[::-1]  # 反转列表 [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]     

23、二维数组变一维数组

       import itertools >>> a = [[1, 2], [3, 4], [5, 6]] >>> i = itertools.chain(*a) >>> list(i) [1, 2, 3, 4, 5, 6]     

24、有索引的迭代

       >>> a = ['Merry', 'Christmas ', 'Day'] >>> for i, x in enumerate(a): ...     print '{}: {}'.format(i, x) ... 0: Merry 1: Christmas 2: Day     

25、列表推导式

       >>> le = [x*2 for x in range(10)] >>> le  # 每个数乘以2 [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]  >>> le = [x for x in range(10) if x%2 == 0] >>> le  # 获取偶数项 [0, 2, 4, 6, 8]     

26、生成器表达式

       >>> ge = (x*2 for x in range(10)) >>> ge <generator object <genexpr> at 0x01948A50> >>> next(ge) 0 >>> next(ge) 2 >>> next(ge) 4 ... >>> next(ge) Traceback (most recent call last):   File "<stdin>", line 1, in <module> StopIteration     

27、集合推导式

       Python  >>> nums = {n**2 for n in range(10)} >>> nums {0, 1, 64, 4, 36, 9, 16, 49, 81, 25}     

28、判断key是否存在字典中

       >>> d = {"1":"a"} >>> d['2'] Traceback (most recent call last):   File "<stdin>", line 1, in <module> KeyError: '2' >>> '1' in d True >>> d['1'] 'a' >>> d.get("1") 'a' >>> d.get("2") >>>     

29、装饰器

       from functools import wraps  def tags(tag_name):     def tags_decorator(func):         @wraps(func)         def func_wrapper(name):             return "<{0}>{1}</{0}>".format(tag_name, func(name))         return func_wrapper     return tags_decorator  @tags("p") def get_text(name):     """returns some text"""     return "Hello " + name  print(get_text("Python"))  >>><p>Hello Python</p>     

30、字典子集

       >>> def sub_dicts(d, keys): ...     return {k:v for k, v in d.items() if k in keys} ... >>> sub_dicts({1:"a", 2:"b", 3:"c"}, [1,2]) {1: 'a', 2: 'b'}     

31、反转字典

       >>> d = {'a': 1, 'b': 2, 'c': 3, 'd': 4} >>> >>> zip(d.values(), d.keys()) <zip object at 0x019136E8> >>> z = zip(d.values(), d.keys()) >>> dict(z) {1: 'a', 2: 'b', 3: 'c', 4: 'd'}     

32、具名元组

       >>> from collections import namedtuple >>> Point = namedtuple("Point", "x,y") >>> p = Point(x=1, y=2) >>> p.x 1 >>> p[0] 1 >>> p.y 2 >>> p[1] 2     

33、设置字典默认值

       >>> d = dict() >>> if 'a' not in d: ...     d['a'] = [] ... >>> d['a'].append(1) >>> d {'a': [1]}  >>> d.setdefault('b',[]).append(2) >>> d {'a': [1], 'b': [2]} >>>     

34、有序字典

       >>> d = dict((str(x), x) for x in range(10)) >>> d.keys() # key 无序 dict_keys(['0', '1', '5', '9', '4', '6', '7', '8', '2', '3'])   >>> from collections import OrderedDict >>> m = OrderedDict((str(x), x) for x in range(10)) >>> m.keys() # key 按照插入的顺序排列 odict_keys(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])     

35、列表中最大最小的前n个数

       >>> import heapq a = [51, 95, 14, 65, 86, 35, 85, 32, 8, 98] >>> heapq.nlargest(5,a) [98, 95, 86, 85, 65] >>> heapq.nsmallest(5,a) [8, 14, 32, 35, 51] >>>     

36、打开文件

       >>> with open('foo.txt', 'w') as f: ...     f.write("hello") ...     

37、两个列表组合成字典

       list_1 = ["One","Two","Three"] list_2 = [1,2,3] dictionary = dict(zip(list_1, list_2)) print(dictionary)     

38、去除列表中重复元素

       my_list = [1,4,1,8,2,8,4,5] my_list = list(set(my_list)) print(my_list)     

39、打印日历

       import calendar  >>> print(calendar.month(2021, 1))     January 2021 Mo Tu We Th Fr Sa Su              1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31     

40、匿名函数

       def add(a, b):     return a+b     

等价于

       >>> add = lambda a,b:a+b >>> add(1,2) 3     

如果对您有帮助,麻烦您给我点个小小的赞,后面我还会写更多实用技巧,关注我不迷路。如果还整准备入门,可以了解下面这个闯关式教学

类似的话题

  • 回答
    老兄,说到 Python 的“奇技淫巧”,那可真是说不完道不尽!这语言就像一把瑞士军刀,你以为你用得很顺手了,结果一挖,嘿,还有更骚的操作藏在后面呢。咱们不谈那些基础的列表推导式、生成器表达式什么的了,这些只能算是入门级的小技巧。今天我给你唠点真正让别人看了直呼“卧槽”的。 1. “借壳上市”:函数.............
  • 回答
    Python 和 C 语言,这两门语言可以说是编程界的两座高峰,它们各自拥有庞大的用户群体和广泛的应用领域,但它们在设计理念、语法特性、执行方式乃至学习曲线等方面,都存在着显著的差异。理解这些不同,对于选择合适的工具、深入学习编程至关重要。咱们先从它们的“出身”和“性格”说起。1. 设计哲学与定位:.............
  • 回答
    有些人可能会说,Python“不适合”游戏开发,但这就像说一辆卡车“不适合”在赛道上飙车一样——它不是它的主要设计用途,但它仍然能做到,只是性能和体验可能不如专门的跑车。Python在游戏开发领域的确有一些显而易见的“软肋”,但说它“完全不适合”就有些绝对了。问题的关键在于,很多我们认为“游戏”的东.............
  • 回答
    咱们就来聊聊这几门编程语言,它们各自有什么“拿手好戏”,主要都用在哪些地方。别担心,这里不会有那种死板的AI介绍,咱们就当朋友聊天,说点实在的。 C:打地基的“硬汉”想象一下,你想盖一栋摩天大楼,你得先打最坚实的地基,对吧?C语言就像这个地基的奠基者,它非常接近计算机硬件,能让你直接控制内存、寄存器.............
  • 回答
    一股暗流正在技术世界涌动,那些名不见经传的新兴语言,比如 Vlang 和 Nim,正悄然积蓄力量。它们不像 Go、Rust 或 Python 那样声名显赫,拥有庞大的社区和成熟的生态,但它们身上散发出的独特魅力,足以让那些追求更高效、更简洁、更纯粹开发体验的开发者们眼前一亮。那么,这些“后起之秀”是.............
  • 回答
    .......
  • 回答
    Python 语言的强制缩进,也就是“代码块”的定义完全依赖于缩进,而不是像许多其他语言那样使用花括号 `{}` 或 `begin/end` 等关键字,这是一个在开发者社区中长期存在争议的话题。 是否是“败笔”,很大程度上取决于个人的编程习惯、对代码可读性的侧重以及所处的开发环境。下面我将详细阐述支.............
  • 回答
    当然,关于将C语言和Python源代码转换为汇编语言的工具,以及它们的工作原理,我来详细地给你讲讲。 将C语言源代码转换成汇编语言这绝对是完全可行的,而且是编译器的核心功能之一。C语言作为一种高级编程语言,它的目标就是要被转换成机器能够直接理解的低级指令,而汇编语言就是机器码的一种助记符表示。核心工.............
  • 回答
    这个问题嘛,就像问“我该选择披萨还是汉堡?”一样,答案很大程度上取决于你想做什么,以及你对“前景好”的定义。Python和Go,说实话,现在都处于职业生涯的黄金时期,硬要说谁“更好”,实在是个见仁见智的事。不过,咱们可以把它们俩的特点拉出来遛遛,看看哪个更对你的胃口。Python:万金油,社区的拥抱.............
  • 回答
    初次接触编程,很多人都会面临选择 Python 还是 C 语言的困惑,尤其是当有人已经尝试过 C 语言并且感到吃力时,这种迷茫感会更加强烈。其实,这两种语言在设计理念和学习曲线上有显著的差异,也因此适合不同类型的学习者和项目需求。C 语言之所以被很多人认为“难”,很大程度上是因为它是一门相对底层的语.............
  • 回答
    这个问题可以说是编程学习领域里一个永恒的讨论点,很多人在刚踏入编程世界时都会纠结于此。其实,“哪个更好”没有绝对的答案,更关键的是“哪个更适合你”,以及你学习的目标是什么。为了让你有个更清晰的认识,咱们掰开了揉碎了聊聊 Python 和 C 语言各自的特点、优势、学习曲线以及适合的应用场景。 Pyt.............
  • 回答
    .......
  • 回答
    Python 绝对是一门对面向对象编程 (OOP) 非常友好的语言,并且在很多方面都做得非常出色,让 OOP 的实践变得直观、简洁且强大。但正如所有技术一样,总有改进的空间。下面我将详细阐述 Python 在 OOP 方面的友好性,以及它可能存在的改进空间: Python 对面向对象编程的友好性体现.............
  • 回答
    这可真是个有趣的问题,关于函数重载,语言设计者们确实各有取舍。不是所有“新语言”都不支持函数重载,比如 C++ 和 Java 这两大主流语言就都提供了这项功能。但是,你提到的 Python, Go, 和 Rust,它们确实都没有原生支持函数重载的机制。这背后其实是这些语言在设计哲学和目标上的不同选择.............
  • 回答
    有人说C语言过时了,要学就学Python,这是一种常见的观点,尤其是在初学者中。要反驳这种观点,我们可以从多个角度进行深入分析,强调C语言的独特价值和在现代技术生态中的重要性。以下是一个详细的反驳思路:核心观点:C语言并未过时,而是以一种更核心、更基础的方式存在,与Python等高级语言相辅相成,不.............
  • 回答
    关于“Swift 的 RC4 运算效能是 Python 的 220 倍”这一说法,可能存在几个关键误解或信息混淆。以下是详细分析和澄清: 1. RC4 是加密算法,不是编程语言特性 RC4 是一种对称加密算法(流加密),用于数据加密,而非编程语言本身的特性。Swift 和 Python 本身没.............
  • 回答
    在处理大型项目时,Python 的表现究竟如何?这个问题就像问一条船在航行中是否适合远洋,答案并非简单的“好”或“坏”,而是取决于你如何使用它,以及你期望它承担什么样的角色。要说Python是“烂语言”,未免过于武断,也忽略了它在无数成功的大型项目中所扮演的关键角色。然而,在某些特定场景下,Pyth.............
  • 回答
    潘石屹说Python是最接近日常语言的编程语言,这个说法挺有意思的,也挺值得说道说道的。咱们先不急着站队,而是把这个事儿掰开揉碎了聊聊。首先,咱们得明白“日常语言”是个啥概念。咱们平时说话,用的是中文、英文,还有别的各种语言,这些语言的特点是什么?一是自然、灵活、表意丰富。一句“天气不错啊”,背后可.............
  • 回答
    好多人在学 Python 用 NumPy 的时候,都会有一个疑惑:为什么那些看起来特别“绕”的 NumPy 向量化操作,比如 `a + b` 或者 `np.sin(a)`,比我写一个简单的 `for` 循环还要快那么多?这到底是为什么?感觉 NumPy 像是偷懒了,但实际上它是在“偷”性能。咱们就来.............
  • 回答
    Python 作为一种强大的数据科学语言,拥有丰富多样的数据可视化库,为用户提供了从基础绘图到复杂交互式可视化的广泛选择。除了 `matplotlib` 这个被誉为“万能瑞士军刀”的库之外,还有许多其他优秀的库,它们在特定领域、易用性、交互性或美学风格上各有千秋。下面我将详细介绍一些常用的 Pyth.............

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有