python这门语言怎么样_就语法而言,Python 这个语言怎么样?

会的计算机语言不多,十来种吧。个人看法,python的语法很棒棒啊。

优点一:循环遍历的写法简洁、优雅。

for i in range(100):

do_something(i)

for idx,item in enumerate(anything_that_can_enumerate):

do_something(idx,item)

strng = strng[::-1] #reverse a string

strng = ''.join(c for c in strng if c.isalpha()) # filt a string, drop none alpha chars

如果用其他语言,多半写不出这么简洁优雅的。

优点二:抽象程度高,多态强悍,库代码复用良好

比如计算常用到的分数库、定点数库,Fraction和Decimal类型可以简单地互相转换。这个在动态语言当中,真心是做得很好的了。

优点三:battery included

通常这不能算是语法层面的优点。然而python自带的库,覆盖广、质量高。类似的事情,大家都用同一款库,无疑减少了歧义、差错的机会。

缺点一:语法糖多,容易造成混淆

比较容易写出简短而难理解的代码(当然,不会比perl更糟糕)。

缺点二:解释器不太关心代码的正确性,更依赖程序员本人

比如说,函数可以有时候有返回值有时候没有。丢弃个返回值可以随意。对尾递归没有优化,递归容易溢出、效率也低。等于说对递归的支持,比一些其他的语言不过是半成品。

这个问题下面,好多瞎吐槽的观点:

1、游标卡尺哏。这个根本不是问题。就算语言不强制,缩进排版不严格执行的程序员,都应该拉出来打。那些学生物、统计的,用起python来,能整整齐齐的缩进,绝对是好事。

2、动态类型问题。动态类型是一种设计、选择,并不能说是缺陷。据此说python不太适合大型项目的,请问,有哪个动态类型语言比python更适合大型项目?js?

3、变量名称简化哏。python风格允许一些一望而知、局部使用的变量使用简短的名称,但绝对不滥用简化原则,在标准库里也是同样。像n代表数量,i代表循环计数变量。都是允许的。然而说def xx(a,b): 这样的,不能怨python。在go里面,func xx(a,b interface{}) []interface{} 这样的函数声明,一样也是符合语法规范的。编程的人真心想写烂代码,用什么语言都可以。

第一次参与回答这种问题,鉴于评论区有个拿个别语言特性反复争论的。还是列几段代码,旁观的自行比对,看看不一样的风格吧。举例Codewars上很简单一道题目,和几种语言当中网友的解(选择高赞当中比较简短的)。先说明,这几种解的代码,不是完全对等的翻译,是不同的人做出的等价的解而已,代码风格都未见得是怎么特别好。不过不同语言的语法差别可见一斑。

先看问题的定义:

The aim of the kata is to decompose n! (factorial n) into its prime factors.

Examples:

n = 12; decomp(12) -> "2^10 * 3^5 * 5^2 * 7 * 11"

since 12! is divisible by 2 ten times, by 3 five times, by 5 two times and by 7 and 11 only once.

n = 22; decomp(22) -> "2^19 * 3^9 * 5^4 * 7^3 * 11^2 * 13 * 17 * 19"

n = 25; decomp(25) -> "2^22 * 3^10 * 5^6 * 7^3 * 11^2 * 13 * 17 * 19 * 23"

Prime numbers should be in increasing order. When the exponent of a prime is 1 don't put the exponent.

Notes

the function is decomp(n) and should return the decomposition of n! into its prime factors in increasing order of the primes, as a string.

factorial can be a very big number (4000! has 12674 digits, n will go from 300 to 4000).

In Fortran - as in any other language - the returned string is not permitted to contain any redundant trailing whitespace: you can use dynamically allocated character strings.

Python是这样的风格:

def decomp(n):

f = {}

for i in range(2, n+1):

for j in range(2, int(i**0.5)+1):

while i%j==0:

i = i//j

f[j] += 1

if i!=1:

if i in f: f[i] += 1

else: f[i] = 1

return ' * '.join(["{}^{}".format(i, f[i]) if f[i]>1 else str(i) for i in sorted(f)])

Swift最短是这样的风格:

import Foundation

func decomp(_ m: Int) -> String {

return (1...m).reduce(into: Array(repeating: 0, count: m + 1)) { arr, num in

var i = 2, num = num

while num > 0 && i <= num {

if num % i != 0 { i += 1 }

else { arr[i] += 1; num /= i }

}

}.enumerated()

.filter { $1 != 0 }

.map { $1 == 1 ? "\($0)" : "\($0)^\($1)" }

.joined(separator: " * ")

}

R的解当中,最简短的是这样:

primes=c(2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,1607,1609,1613,1619,1621,1627,1637,1657,1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1847,1861,1867,1871,1873,1877,1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,1979,1987,1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,2069,2081,2083,2087,2089,2099,2111,2113,2129,2131,2137,2141,2143,2153,2161,2179,2203,2207,2213,2221,2237,2239,2243,2251,2267,2269,2273,2281,2287,2293,2297,2309,2311,2333,2339,2341,2347,2351,2357,2371,2377,2381,2383,2389,2393,2399,2411,2417,2423,2437,2441,2447,2459,2467,2473,2477,2503,2521,2531,2539,2543,2549,2551,2557,2579,2591,2593,2609,2617,2621,2633,2647,2657,2659,2663,2671,2677,2683,2687,2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,2749,2753,2767,2777,2789,2791,2797,2801,2803,2819,2833,2837,2843,2851,2857,2861,2879,2887,2897,2903,2909,2917,2927,2939,2953,2957,2963,2969,2971,2999,3001,3011,3019,3023,3037,3041,3049,3061,3067,3079,3083,3089,3109,3119,3121,3137,3163,3167,3169,3181,3187,3191,3203,3209,3217,3221,3229,3251,3253,3257,3259,3271,3299,3301,3307,3313,3319,3323,3329,3331,3343,3347,3359,3361,3371,3373,3389,3391,3407,3413,3433,3449,3457,3461,3463,3467,3469,3491,3499,3511,3517,3527,3529,3533,3539,3541,3547,3557,3559,3571,3581,3583,3593,3607,3613,3617,3623,3631,3637,3643,3659,3671,3673,3677,3691,3697,3701,3709,3719,3727,3733,3739,3761,3767,3769,3779,3793,3797,3803,3821,3823,3833,3847,3851,3853,3863,3877,3881,3889,3907,3911,3917,3919,3923,3929,3931,3943,3947,3967,3989)

factors = function(n){

prime_count=1

new_wector=NULL

while (n!=1) {

if(n%%primes[prime_count]==0){

n=n/primes[prime_count]

new_wector=c(new_wector,primes[prime_count])

}

else{

prime_count=prime_count+1

}

}

a=new_wector

return(a)

}

decomp <- function(n) {

n=seq(2,n,1)

b=unlist(lapply(n,factors))

c=unique(b)

e=as.vector(table(b))

d=paste0(c,"^",e,' * ',collapse = '')

f=gsub("\\^1 \\*"," *",d)

e=substr(f,start = 1,stop=nchar(as.character(f))-3)

return(e)

}

Rust的解当中,比较简洁的是这样的:

usestd::collections::BTreeMap;fn factorize(n: i32)-> Option<(i32,i32)>{letmutp=2;loop{ifp*p>n{returnNone;}ifn%p==0{returnSome((n/p,p));}p+=ifp==2{1}else{2};}}fn decomp(n: i32)-> String {ifn<=1{returnn.to_string()}letmutfactors=BTreeMap::new();foriin2..=n{letmutn=i;whileletSome((r,p))=factorize(n){factors.entry(p).and_modify(|e|*e+=1).or_insert(1);n=r;}factors.entry(n).and_modify(|e|*e+=1).or_insert(1);}factors.iter().map(|(&p,&e)|{ife==1{p.to_string()}else{format!("{}^{}",p,e)}}).collect::>().join(" * ")}

Go的解当中最简洁的是这样的:

package kata

import (

"strings"

"fmt"

)

func Decomp(n int) string {

primes := make(map[int]int, 0)

for i := 2; i <= n; i++ {

j, k := 2, i

for j * j <= i {

if k % j == 0 {

primes[j]++

k /= j

} else {

j++

}

}

primes[k]++

}

b := new(strings.Builder)

for i := 2; i <= n; i++ {

if primes[i] > 1 {

fmt.Fprintf(b, "%d^%d * ", i, primes[i])

} else if primes[i] == 1 {

fmt.Fprintf(b, "%d * ", i)

}

}

s := b.String()

return s[:len(s) - 3]

}

Julia的比较简洁的解是这样的:

module Fact

export decomp

function create_string_output(factors::Array{Pair{Int64,Int64},1})::String

stringify(pair::Pair) = if pair[2] > 1 "$(pair[1])^$(pair[2])" else "$(pair[1])" end

return [stringify(x) for x in factors] |> x -> join(x, " * ")

end

function largest_power(n::Int64, p::Int64)::Int64

x = 0

while (n > 0)

n/=p

x += trunc(Int, n)

end

return x

end

function is_prime(n::Int64)::Bool

if n <= 1 return false end

for i in 2:(n-1) if n%i == 0 return false end end

return true

end

function decomp(n::Int64)::String

count_map = Dict{Int64, Int64}()

possible_prime::Int64 = 2

exponent::Int64 = -1

still_running = true

while (exponent != 0)

exponent = largest_power(n, possible_prime)

is_valid_prime = is_prime(possible_prime) && (exponent>0)

if is_valid_prime count_map[possible_prime] = exponent end

possible_prime+=1

end

pairs = collect(count_map) |> pair_array -> sort(pair_array, by= x -> x[1])

return create_string_output(pairs)

end

end

看这个Haskell的。去掉Import、注释,的确比上面的python解短。算不算简洁易懂,大家自己判断吧:

module FactorialDecomposition.Kata (decomp) where

import Data.List

import qualified Data.Map.Strict as Map

decomp :: Int -> String

decomp n = intercalate " * " $ Map.elems $ Map.mapWithKey (\k v -> (show k) ++ (if v > 1 then "^" ++ show v else "")) $ foldl (\m -> Map.unionWith (+) m . primeFactors) Map.empty [2..n] where

-- Helper function - decompose integer into prime factors

-- Adapted from https://www.codewars.com/kata/reviews/58799ea408d0c8b22a000107/groups/58a4a1704aac53766e00141a

primeFactors :: Int -> Map.Map Int Int

primeFactors 0 = Map.empty

primeFactors 1 = Map.empty

primeFactors n = Map.insertWith (+) first 1 $ primeFactors (div n first) where

first = head $ [ x | x <- [2..n], mod n x == 0]

以上不过是语言风格对比,较真其中的细节恐怕就没啥意思了。最后,为了防杠精又来说,有用别的语言行数更短的解法(确实有),我改下上面的python解,不过于损失可读性的情况下,给一个更简短的解,9行吧(当然还能更短,Codewars上有个3行的解):

def decomp(n):

f = {}

for i in range(2, n+1):

for j in range(2, int(i**0.5)+1):

while i%j==0:

i,f [j] = i//j, f[j]+1 if j in f else 1

if i > 1:

f[i] = f[i]+1 if i in f else 1

return ' * '.join("{}^{}".format(i, f[i]) if f[i]>1 else str(i) for i in sorted(f))

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值