A more in-depth version would be something like:
ClearAll[Arities]
Arities[g_]:=Module[{dv,bl,blns,bls,opts,num},
dv=DownValues[g];
dv=dv[[All,1]];
bl=Count[#,Verbatim[Blank[]],\[Infinity]]&/@dv;
bls=Count[#,Verbatim[BlankSequence[]],\[Infinity]]&/@dv;
blns=Count[#,Verbatim[BlankNullSequence[]],\[Infinity]]&/@dv;
opts=Count[#,Verbatim[Optional][_,_],\[Infinity]]&/@dv;
num=MapThread[#1+If[#2>0,#2 {1,\[Infinity]},0]+If[#3>0, #3{0,\[Infinity]},0]-#4{1,0}&,{bl,bls,blns,opts}];
{dv,bl,bls,blns,opts,num}
]
ClearAll[F]
F[x_, y_, z_, f_, g_: 2, x2_: 3] := 14
F[x_, y_, z_, f_, g_: 2] := 14
F[x_, z_, f_, y___] := 14
F[x_, z_, y__] := 14
F[x_, y_] := 14
F[x_] := 23
F[] := 12
Arities[F] // Transpose // Grid
returns:

Which is a list of Definition, # of Blanks, # of BlankSequences, # of BlankNullSequenced, # of optional arguments, and range of number of arguments.
May I ask why you need the arities of the function? I can't really think of a use in 'normal' calculations...